65 Commits

Author SHA1 Message Date
auria.mg
e7a2988273 Remove translations that are not complete enough 2016-06-26 19:33:40 -04:00
auria.mg
8691dfb2d4 Update translations from transifex 2016-06-26 19:28:27 -04:00
auria.mg
edde451551 Update version number 2016-06-26 19:22:05 -04:00
auria.mg
851bd36ce1 Add new improved race end sound 2016-06-24 20:22:48 -04:00
Rémi Verschelde
27bcdb341e Fix double slash in include
Triggers a weird 9 year old RPM bug when extracting
debugging information for the compiled binary:
https://bugzilla.redhat.com/show_bug.cgi?id=304121
2016-06-16 20:23:55 -04:00
hiker
17649cc502 Don't include ilk (linker) files, properly remove shortcut to editor. 2016-06-14 23:03:21 +10:00
Benau
f4c8c72e16 Remove a unneeded setting 2016-06-13 09:09:49 +08:00
Benau
b6027e0f18 Fix default value of m_angular_damping 2016-06-12 08:10:49 +08:00
hiker
9d94473c05 Fixed compiler warning. 2016-06-10 16:06:35 +10:00
hiker
85c05098b1 Fixed missing collision callbacks for e.g. soccer balls. 2016-06-10 13:13:35 +10:00
auria.mg
0e9e2af89e Update translation authors. Also modify the authors script to be easier to use 2016-06-08 19:51:30 -04:00
auria.mg
08f407c55c More verson and translation stuff 2016-06-08 19:45:28 -04:00
auria.mg
fe8dcdf478 Set version number to 0.9.2-rc1. Update translations from transifex 2016-06-08 19:42:25 -04:00
hiker
6281b479ac Made more physics parameters for objects adjustable in the xml file
(for now to support a puck).
2016-06-07 11:49:29 +10:00
hiker
489182749b Added support for setting the restitution for physical objects. 2016-06-07 11:49:18 +10:00
auria.mg
d3ce304d28 Update changelog 2016-06-06 19:55:44 -04:00
Deve
d5c403dfe3 One more tweak..... 2016-06-04 00:08:50 +02:00
Deve
9f0d22c013 Define constants in glew cmake file before 'add_library' function.
It was working for me as it was before, but based on this comment: 10488bc79a (commitcomment-17724549) it looks that some cmake versions may ignore definitions that are defined below add_library.
2016-06-03 06:49:28 +02:00
Benau
bf3b88e458 Fix #2498 2016-06-02 08:31:08 +08:00
Benau
2ab2953879 Fix warning 2016-06-01 10:13:24 +08:00
Benau
c1ebcf8165 Remove not too useful angle calculation
Fix a bug in reverse position returned
2016-06-01 10:13:12 +08:00
Benau
92b37d6de4 More detailed comments 2016-06-01 10:13:04 +08:00
Benau
5ad6be3d5b Don't use getDistance from battle graph for kart
As sometimes it will return 0 if kart is on unknown node

Also try to make banana avoidance better
2016-06-01 10:12:55 +08:00
Benau
c7b01b8e23 Use an improved turn radius determination 2016-06-01 10:12:45 +08:00
Benau
b45a5cec2e Make gift package playable 2016-06-01 10:12:28 +08:00
hiker
745df386e4 Added backtwards force when reversing. That fixes the problem that a
kart might sometimes get stuck when driving backwards.
2016-05-31 15:11:52 +10:00
hiker
b9cb30bbd7 Fixed FreeBSD builds (freebsd installs Freetype etc in /usr/local/lib,
but does not search in that directory for libraries).
2016-05-31 13:44:19 +10:00
Deve
8b4cd23329 One more tweak in SSAO.
Just use mod(x, 6.283185307179586) as suggested by mesa developer, instead converting it to degrees and back to radians.
2016-05-26 11:49:32 +02:00
Deve
19f107d23f Fixed a bug in my previous commit.
I forgot that sin and cos functions want angle value in radians.
Now the code looks a bit ugly, but generates proper values.
2016-05-26 02:40:16 +02:00
Benau
d7684d7cea Try to make AI work like zidane 2016-05-26 08:27:15 +08:00
Deve
2dbffbe7fd Fixed SSAO on intel.
In ssao.frag we are computing theta valaue and it looks that intel driver doesn't like too big values for sinus and cosinus computations.

I just used modulo 360 to store lower angle values in theta variable.
2016-05-25 23:17:39 +02:00
deve
e841ae4526 Restore old check for geometry shaders availability on non-linux platforms.
This is done to avoid too many modifications before release.
2016-05-25 13:26:23 +02:00
Deve
17867219a0 Added a check for GL_ARB_explicit_attrib_location extension.
It is enabled by default for OpenGL 3.3, but we need it for some of our shaders in render_geometry.cpp (which are OpenGL >= 3.2) and also for InstancedColorizeShader.
2016-05-24 19:01:40 +02:00
Deve
45b750c01b Fixed shadows and GI for mesa drivers.
The check for GL_ARB_geometry_shader4 doesn't have sense at all because we don't use this extension and our geometry shaders use functionality which is available in core OpenGL 3.2.

The reason that it wasn't working for older mesa versions must be a bug in mesa or maybe missing other functionality (but not GL_ARB_geometry_shader4).

I checked it with mesa 11.2 and current git version and it works fine on intel, nouveau and with software rendering.

It needs some testing because it potentially affects all drivers with OpenGL >= 3.2 on every platform.

If someone could test it with Radeon drivers, I would be really happy to enable it in upcoming release, at least on linux.
2016-05-24 19:01:31 +02:00
Deve
cb58631b5a Fixed an error message when unlocking texture in spherical harmonics.
On some tracks it was reporting following message:
[warn   ] GLWrap: OpenGL debug callback - API
[warn   ] GLWrap:     Error type : ERROR
[warn   ] GLWrap:     Severity : HIGH
[warn   ] GLWrap:     Message : GL_INVALID_VALUE error generated. Size and/or offset out of range.

This fixes #2504
2016-05-24 19:00:17 +02:00
Benau
0333054ca6 Add more defense 2016-05-24 16:02:12 +08:00
Benau
a65d4b0829 Update CHANGELOG.md 2016-05-24 09:14:10 +08:00
Benau
21793191c4 Fix wrong colon 2016-05-21 11:34:59 +08:00
Benau
99d1c48e0a Fix crashes in arena profiling mode
Notice: you need to merge arena_ai_profiling into here to test
2016-05-21 09:26:11 +08:00
Benau
001c7b30ee Use math formula to determine overtake position 2016-05-21 09:26:04 +08:00
Benau
3d95cdc76f Fix goal target not updated when going back
Also fix some unitialized value issue
2016-05-21 09:25:56 +08:00
Benau
0b162984a5 Improvements in soccer mode with minimap
1. Larger ball

2. Draw goal line of two teams in minimap
2016-05-21 09:25:47 +08:00
Benau
a48b88d890 First playable advanced soccer ai 2016-05-21 09:25:38 +08:00
Benau
2b075e7f0f Get rid of two more member values 2016-05-21 09:25:30 +08:00
Benau
4df5a269e8 Remove unneeded memeber 2016-05-21 09:25:21 +08:00
Benau
4049067c50 First version of advanced soccer ai 2016-05-21 09:25:11 +08:00
Benau
2b8e5c09d0 Try to fix lost control for soccer ai 2016-05-21 09:24:02 +08:00
auria.mg
d88bebae1e Update changelog and credits 2016-05-18 20:00:57 -04:00
auria.mg
5b42b43dee Add new volcano track 2016-05-18 19:57:27 -04:00
Benau
7b707a3546 Fix x N items font size
It should depend on screen scaling.
2016-05-18 13:04:06 +08:00
Benau
5c2286f556 Don't crash if missing texture 2016-05-18 10:06:31 +08:00
auria.mg
7f2f62be11 Add higher-res icon 2016-05-14 21:14:56 -04:00
Deve
6b7bc2c67e Update dependencies for Ubuntu
- use officially supported pkg-config instead of pkgconf replacement
- add zlib library to dependencies
- remove GLU library which is not needed at all since this commit: 60dc171700
- add libgl1-mesa-dev and mesa-common-dev which contains OpenGL headers that we need
- use libcurl-gnutls instead of openssl because it is used by default in Debian/Ubuntu for STK and many other projects.
2016-05-14 23:18:00 +02:00
auria.mg
80c8e2ace3 Merge PR 2494 into the 0.9.2 branch 2016-05-13 21:10:03 -04:00
Deve
60dc171700 Don't link libGLU library.
This should allow to run linux static package even if libglu1-mesa package is not installed. And the utilities from GLU library are not used in STK anyway.
2016-05-12 23:39:23 +02:00
auria.mg
cc77d63f5b Undo previous "bugfix", it doesn't work 2016-05-11 19:45:32 -04:00
auria.mg
822fa73b07 Fix camera roll in cutscenes 2016-05-11 19:34:30 -04:00
Deve
b0251cf0b1 Add a workaround for skybox.
The problem was with shader-based pipeline with disabled "advanced effects" in options.

In this case we don't use RTTs and gl_FragCoord contains values in range of whole window. So fo 2 players we still get gl_FragCoord.y = 0..window_size instead of gl_FragCoord.y = 0..window_size/2.

The easiest way to solve it seems to be modulo it by current viewport size. It should be compatible with advanced pipeline as well as single-player games.

Atm. I'm not sure if this should be applied to 0.9.2 branch. It should work fine, but needs some testing.
2016-05-11 09:55:13 +02:00
qwertychouskie
43152ff3ed Update screenshots and description 2016-05-07 23:35:06 -04:00
Benau
e31ea79602 Auto-balance the number of AIs
If there are uneven the number of human players in each team
2016-05-08 08:10:55 +08:00
hiker
5a72ef711c Merge branch '0.9.2' of https://github.com/supertuxkart/stk-code into 0.9.2 2016-05-07 00:15:35 +10:00
hiker
b2447f114f Fixed second location where the kart/playe rname was used. 2016-05-07 00:14:55 +10:00
Benau
c22da37992 Fix determineTurnRadius in ArenaAI
Before this function always return nan/inf/too large number of
radius, now this function will calculate the radius of curvature
correctly.
2016-05-06 22:05:22 +08:00
hiker
7ac674aebd Show the name of the player in the grand prix result screen. 2016-05-06 23:47:26 +10:00
auria.mg
12ea4bc76f Create the 0.9.2 branch, hide networking stuff 2016-05-05 19:54:14 -04:00
133 changed files with 34344 additions and 124210 deletions

View File

@@ -2,12 +2,15 @@
* Ghost replay races by Benau * Ghost replay races by Benau
* Battle mode AI by Benau * Battle mode AI by Benau
* Soccer mode AI by Benau * Soccer mode AI by Benau
* New icy soccer field by samuncle and Benau
* New subsea track by samuncle * New subsea track by samuncle
* New volcano track by Ponzino
* TTF font rendering by Benau * TTF font rendering by Benau
* Kart properties refactor by Flakebi * Kart properties refactor by Flakebi
* Scripting work under the hood * Scripting work under the hood
* Work on the track editor by mhp * Work on the track editor by mhp
* Tweak to challenges * Tweak to challenges
* New farm track song by 0zone0ne and Krobonil
* Bugfixes * Bugfixes
## SuperTuxKart 0.9.1 ## SuperTuxKart 0.9.1

View File

@@ -1,6 +1,6 @@
# root CMakeLists for the SuperTuxKart project # root CMakeLists for the SuperTuxKart project
project(SuperTuxKart) project(SuperTuxKart)
set(PROJECT_VERSION "0.9.1") set(PROJECT_VERSION "0.9.2")
cmake_minimum_required(VERSION 2.8.4) cmake_minimum_required(VERSION 2.8.4)
if(NOT (CMAKE_MAJOR_VERSION VERSION_LESS 3)) if(NOT (CMAKE_MAJOR_VERSION VERSION_LESS 3))
@@ -68,6 +68,7 @@ add_subdirectory("${PROJECT_SOURCE_DIR}/lib/enet")
include_directories("${PROJECT_SOURCE_DIR}/lib/enet/include") include_directories("${PROJECT_SOURCE_DIR}/lib/enet/include")
# Build glew library # Build glew library
add_definitions(-DGLEW_NO_GLU)
add_subdirectory("${PROJECT_SOURCE_DIR}/lib/glew") add_subdirectory("${PROJECT_SOURCE_DIR}/lib/glew")
include_directories("${PROJECT_SOURCE_DIR}/lib/glew/include") include_directories("${PROJECT_SOURCE_DIR}/lib/glew/include")
@@ -365,6 +366,11 @@ if(UNIX AND NOT APPLE)
endif() endif()
endif() endif()
# FreeBSD does not search in /usr/local/lib, but at least Freetype is installed there :(
if(${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD")
SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -L/usr/local/lib")
endif()
if(APPLE) if(APPLE)
# In theory it would be cleaner to let CMake detect the right dependencies. In practice, this means that if a OSX user has # In theory it would be cleaner to let CMake detect the right dependencies. In practice, this means that if a OSX user has
# unix-style installs of Vorbis/Ogg/OpenAL/etc. they will be picked up over our frameworks. This is blocking when I make releases : # unix-style installs of Vorbis/Ogg/OpenAL/etc. they will be picked up over our frameworks. This is blocking when I make releases :

View File

@@ -1,6 +1,7 @@
# SuperTuxKart Installation Instructions # SuperTuxKart Installation Instructions
Note: If you obtained this source code from Github, you also need to download the game assets from Sourceforge using SVN. Note: If you obtained this source code from Github, you also need to download
the game assets from Sourceforge using SVN.
`svn checkout https://svn.code.sf.net/p/supertuxkart/code/stk-assets stk-assets` `svn checkout https://svn.code.sf.net/p/supertuxkart/code/stk-assets stk-assets`
@@ -26,8 +27,10 @@ First, make sure that you have the following packages installed:
Ubuntu command: Ubuntu command:
``` ```
sudo apt-get install autoconf automake build-essential cmake libogg-dev libvorbis-dev libopenal-dev libxxf86vm-dev \ sudo apt-get install build-essential cmake libbluetooth-dev \
libgl1-mesa-dev libglu1-mesa-dev libcurl4-openssl-dev libfribidi-dev libbluetooth-dev libxrandr-dev libfreetype6-dev libcurl4-gnutls-dev libfreetype6-dev libfribidi-dev libgl1-mesa-dev \
libjpeg-dev libogg-dev libopenal-dev libpng-dev libvorbis-dev libxrandr-dev \
mesa-common-dev pkg-config zlib1g-dev
``` ```
Unpack the files from the tarball like this: Unpack the files from the tarball like this:

Binary file not shown.

View File

@@ -17,11 +17,11 @@
<key>CFBundlePackageType</key> <key>CFBundlePackageType</key>
<string>APPL</string> <string>APPL</string>
<key>CFBundleShortVersionString</key> <key>CFBundleShortVersionString</key>
<string>0.8.1</string> <string>0.9.2-rc1</string>
<key>CFBundleSignature</key> <key>CFBundleSignature</key>
<string>SPTK</string> <string>SPTK</string>
<key>CFBundleVersion</key> <key>CFBundleVersion</key>
<string>0.8.1</string> <string>0.9.2-rc1</string>
<key>CSResourcesFileMapped</key> <key>CSResourcesFileMapped</key>
<true/> <true/>
<key>LSMinimumSystemVersion</key> <key>LSMinimumSystemVersion</key>

View File

@@ -2,7 +2,7 @@
<challenge version="2"> <challenge version="2">
<track id="cocoa_temple" laps="3"/> <track id="cocoa_temple" laps="3"/>
<mode major="single" minor="quickrace"/> <mode major="single" minor="quickrace"/>
<requirements trophies="15"/> <requirements trophies="5"/>
<hard> <hard>
<karts number="5"/> <karts number="5"/>

View File

@@ -0,0 +1,19 @@
<?xml version="1.0"?>
<challenge version="2">
<track id="volcano_island" laps="2"/>
<mode major="single" minor="quickrace"/>
<requirements trophies="15"/>
<hard>
<karts number="5"/>
<requirements position="1"/>
</hard>
<medium>
<karts number="4"/>
<requirements position="1"/>
</medium>
<easy>
<karts number="4"/>
<requirements position="1"/>
</easy>
</challenge>

View File

@@ -5,7 +5,7 @@
<track id="greenvalley" laps="2" reverse="false" /> <track id="greenvalley" laps="2" reverse="false" />
<track id="mansion" laps="3" reverse="false" /> <track id="mansion" laps="3" reverse="false" />
<track id="stk_enterprise" laps="3" reverse="false" /> <track id="stk_enterprise" laps="3" reverse="false" />
<track id="city" laps="2" reverse="false" /> <track id="volcano_island" laps="2" reverse="false" />
</supertuxkart_grand_prix> </supertuxkart_grand_prix>

View File

@@ -5,6 +5,7 @@
<card is="Intel(R) HD Graphics 3000" os="windows" disable="FramebufferSRGBWorking"/> <card is="Intel(R) HD Graphics 3000" os="windows" disable="FramebufferSRGBWorking"/>
<card contains="Intel" os="osx" disable="GI"/> <card contains="Intel" os="osx" disable="GI"/>
<card contains="Intel" os="linux" version="<11.2" disable="ComputeShader"/> <card contains="Intel" os="linux" version="<11.2" disable="ComputeShader"/>
<card contains="Intel" os="linux" version="<11.2" disable="GeometryShader"/>
<card contains="Intel" os="linux" version="<16.0" disable="FramebufferSRGBCapable"/> <card contains="Intel" os="linux" version="<16.0" disable="FramebufferSRGBCapable"/>
<card contains="Intel" os="linux" version="<11.2" disable="TextureCompressionS3TC"/> <card contains="Intel" os="linux" version="<11.2" disable="TextureCompressionS3TC"/>
<card contains="Intel" os="windows" disable="TextureCompressionS3TC"/> <card contains="Intel" os="windows" disable="TextureCompressionS3TC"/>
@@ -15,11 +16,11 @@
<card contains="NVIDIA" disable="ShaderAtomicCounters"/> <card contains="NVIDIA" disable="ShaderAtomicCounters"/>
<card contains="Mesa" os="linux" version="<10.3" disable="BufferStorage"/> <card contains="Mesa" os="linux" version="<10.3" disable="BufferStorage"/>
<card contains="Mesa" os="linux" version="<10.3" disable="DriverRecentEnough"/> <card contains="Mesa" os="linux" version="<10.3" disable="DriverRecentEnough"/>
<card contains="Mesa" os="linux" version="<10.6" disable="GeometryShader4"/> <card contains="Mesa" os="linux" version="<11.2" disable="GeometryShader"/>
<card contains="Mesa" os="linux" version="<11.2" disable="TextureCompressionS3TC"/> <card contains="Mesa" os="linux" version="<11.2" disable="TextureCompressionS3TC"/>
<card contains="Gallium" os="linux" version="<10.3" disable="BufferStorage"/> <card contains="Gallium" os="linux" version="<10.3" disable="BufferStorage"/>
<card contains="Gallium" os="linux" version="<10.3" disable="DriverRecentEnough"/> <card contains="Gallium" os="linux" version="<10.3" disable="DriverRecentEnough"/>
<card contains="Gallium" os="linux" version="<10.6" disable="GeometryShader4"/> <card contains="Gallium" os="linux" version="<11.2" disable="GeometryShader"/>
<card contains="Gallium" os="linux" version="<11.2" disable="TextureCompressionS3TC"/> <card contains="Gallium" os="linux" version="<11.2" disable="TextureCompressionS3TC"/>
<!-- On osx radeon appears to have different version numbers, e.g. <!-- On osx radeon appears to have different version numbers, e.g.
1.32.20 --> 1.32.20 -->

View File

@@ -9,7 +9,9 @@
<spacer height="25" width="10"/> <spacer height="25" width="10"/>
<tabs id="profile_tabs" height="10%" max_height="110" x="2%" width="98%" align="center"> <tabs id="profile_tabs" height="10%" max_height="110" x="2%" width="98%" align="center">
<!--
<icon-button id="tab_servers" width="128" height="128" icon="gui/main_network.png"/> <icon-button id="tab_servers" width="128" height="128" icon="gui/main_network.png"/>
-->
<icon-button id="tab_achievements" width="128" height="128" icon="gui/gp_copy.png" <icon-button id="tab_achievements" width="128" height="128" icon="gui/gp_copy.png"
I18N="Section in the profile screen" text="Achievements"/> I18N="Section in the profile screen" text="Achievements"/>
<icon-button id="tab_friends" width="128" height="128" icon="gui/options_players.png"/> <icon-button id="tab_friends" width="128" height="128" icon="gui/options_players.png"/>

View File

@@ -9,7 +9,7 @@
<spacer height="25" width="10"/> <spacer height="25" width="10"/>
<tabs id="profile_tabs" height="10%" max_height="110" x="2%" width="98%" align="center"> <tabs id="profile_tabs" height="10%" max_height="110" x="2%" width="98%" align="center">
<icon-button id="tab_servers" width="128" height="128" icon="gui/main_network.png"/> <!--<icon-button id="tab_servers" width="128" height="128" icon="gui/main_network.png"/>-->
<icon-button id="tab_achievements" width="128" height="128" icon="gui/gp_copy.png"/> <icon-button id="tab_achievements" width="128" height="128" icon="gui/gp_copy.png"/>
<icon-button id="tab_friends" width="128" height="128" icon="gui/options_players.png" <icon-button id="tab_friends" width="128" height="128" icon="gui/options_players.png"
I18N="Section in the profile screen" text="Friends"/> I18N="Section in the profile screen" text="Friends"/>

View File

@@ -8,7 +8,7 @@
<spacer height="25" width="10"/> <spacer height="25" width="10"/>
<tabs id="profile_tabs" height="10%" max_height="110" x="2%" width="98%" align="center"> <tabs id="profile_tabs" height="10%" max_height="110" x="2%" width="98%" align="center">
<icon-button id="tab_servers" width="128" height="128" icon="gui/main_network.png"/> <!--<icon-button id="tab_servers" width="128" height="128" icon="gui/main_network.png"/>-->
<icon-button id="tab_achievements" width="128" height="128" icon="gui/gp_copy.png"/> <icon-button id="tab_achievements" width="128" height="128" icon="gui/gp_copy.png"/>
<icon-button id="tab_friends" width="128" height="128" icon="gui/options_players.png" /> <icon-button id="tab_friends" width="128" height="128" icon="gui/options_players.png" />
<icon-button id="tab_settings" width="128" height="128" icon="gui/main_options.png" <icon-button id="tab_settings" width="128" height="128" icon="gui/main_options.png"

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.9 KiB

After

Width:  |  Height:  |  Size: 23 KiB

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,5 @@
#!/usr/bin/env python #!/usr/bin/env python
# -*- coding: utf-8 -*-
# A simple script that adds all authors from transifex, which are # A simple script that adds all authors from transifex, which are
# listed in comments at the beginning of the file, to the # listed in comments at the beginning of the file, to the
# 'translator-credits' translations - where launchpad added them # 'translator-credits' translations - where launchpad added them
@@ -19,75 +19,79 @@ import re
import sys import sys
if __name__ == "__main__": if __name__ == "__main__":
if len(sys.argv)!=2: if len(sys.argv) < 2:
print "Usage: getpo_authors.py PATH_TO_PO_FILE" print "Usage: getpo_authors.py PATH_TO_PO_FILE"
sys.exit(-1) sys.exit(-1)
f = open(sys.argv[1], "r") for filename in sys.argv[1:]:
if not f: print("Processing file ", filename)
print "Can not find", sys.argv[1] f = open(filename, "r")
exit if not f:
lines = f.readlines() print "Can not find", filename
exit
lines = f.readlines()
f.close() f.close()
new_authors = [] new_authors = []
found = 0 found = 0
# Find all authors with a simple finite state machine: # Find all authors with a simple finite state machine:
contributions = -1 contributions = -1
line_count = 0 line_count = 0
for i in lines: for i in lines:
line = i[:-1] # remove \n line = i[:-1] # remove \n
if line=="# Translators:": if line=="# Translators:":
found = 1 found = 1
elif found and line[:2]=="# " and line [:14]!="# FIRST AUTHOR": elif found and line[:2]=="# " and line [:14]!="# FIRST AUTHOR":
new_authors.append(line[2:]) new_authors.append(line[2:])
elif line[:5]=="msgid": elif line[:5]=="msgid":
found = 0 found = 0
elif line[:31]== "msgstr \"Launchpad Contributions": elif line[:31]== "msgstr \"Launchpad Contributions":
contributions = line_count contributions = line_count
line_count = line_count + 1 line_count = line_count + 1
# Delete all email addresses - not sure if the authors # Delete all email addresses - not sure if the authors
# would want them to be published # would want them to be published
email=re.compile(" *<.*@.*\..*> *") # one @ and one dot at least email=re.compile(" *<.*@.*\..*> *") # one @ and one dot at least
for i in range(len(new_authors)): for i in range(len(new_authors)):
g = email.search(new_authors[i]) g = email.search(new_authors[i])
if g: if g:
new_authors[i] = new_authors[i][:g.start()] \ new_authors[i] = new_authors[i][:g.start()] \
+ new_authors[i][g.end():] + new_authors[i][g.end():]
# Get the old authors from the translator-credits string: # Get the old authors from the translator-credits string:
if contributions>0: if contributions>0:
# Ignore the first entry, which is "msgstr ...", and the # Ignore the first entry, which is "msgstr ...", and the
# last two characters, which are the '"\n'. # last two characters, which are the '"\n'.
old_authors = lines[contributions][:-2].split("\\n")[1:] old_authors = lines[contributions][:-2].split("\\n")[1:]
for i in range(len(old_authors)): for i in range(len(old_authors)):
old_authors[i] = old_authors[i].strip() old_authors[i] = old_authors[i].strip()
else: else:
old_authors=[] old_authors=[]
all_authors = old_authors + new_authors; all_authors = old_authors + new_authors;
all_authors = sorted(all_authors, key=lambda x: x.lower()) all_authors = sorted(all_authors, key=lambda x: x.lower())
all_authors_string = reduce(lambda x,y: x+"\\n"+y, all_authors, "") all_authors_string = reduce(lambda x,y: x+"\\n"+y, all_authors, "")
credits_line = "msgstr \"Launchpad Contributions:%s\"\n"%all_authors_string credits_line = "msgstr \"Launchpad Contributions:%s\"\n"%all_authors_string
# If no old authors exists, write a new entry: # If no old authors exists, write a new entry:
if contributions==-1: if contributions==-1:
lines.append("\n") lines.append("\n")
lines.append("#: src/states_screens/credits.cpp:209\n") lines.append("#: src/states_screens/credits.cpp:209\n")
lines.append("msgid \"translator-credits\"\n") lines.append("msgid \"translator-credits\"\n")
lines.append(credits_line) lines.append(credits_line)
else: else:
# Otherwise just replace the old contribution string # Otherwise just replace the old contribution string
lines[contributions] = credits_line lines[contributions] = credits_line
# Overwrite old file # Overwrite old file
f = open(sys.argv[1], "w") f = open(filename, "w")
for i in lines: for i in lines:
f.write(i) f.write(i)
f.close() f.close()
print("Done with ", filename)

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -4,7 +4,7 @@ out vec4 FragColor;
void main(void) void main(void)
{ {
vec3 eyedir = vec3(gl_FragCoord.xy / screen, 1.); vec3 eyedir = vec3(mod(gl_FragCoord.xy, screen) / screen, 1.);
eyedir = 2.0 * eyedir - 1.0; eyedir = 2.0 * eyedir - 1.0;
vec4 tmp = (InverseProjectionMatrix * vec4(eyedir, 1.)); vec4 tmp = (InverseProjectionMatrix * vec4(eyedir, 1.));
tmp /= tmp.w; tmp /= tmp.w;

View File

@@ -40,7 +40,7 @@ void main(void)
float bl = 0.0; float bl = 0.0;
float m = log2(r) + 6 + log2(invSamples); float m = log2(r) + 6 + log2(invSamples);
float theta = 2. * 3.14 * tau * .5 * invSamples + phi; float theta = mod(2. * 3.14 * tau * .5 * invSamples + phi, 6.283185307179586);
vec2 rotations = vec2(cos(theta), sin(theta)) * screen; vec2 rotations = vec2(cos(theta), sin(theta)) * screen;
vec2 offset = vec2(cos(invSamples), sin(invSamples)); vec2 offset = vec2(cos(invSamples), sin(invSamples));

1
data/supertuxkart.0.9.2 Normal file
View File

@@ -0,0 +1 @@
supertuxkart.0.9.2

View File

@@ -8,28 +8,28 @@
<summary>A racing game</summary> <summary>A racing game</summary>
<description> <description>
<p> <p>
SuperTuxKart is a fun 3D kart racing game. Supertuxkart is a free 3D kart racing game, with a focus on having fun over
You can play with up to 4 friends on one PC, racing against each other or realism. You can play with up to 4 friends on one PC, racing against each
just try to beat the computer. other, or try to beat the computer in single-player mode.
</p> </p>
<p> <p>
See the great lighthouse or drive through the sand and visit the pyramids. See the great lighthouse or drive through the sand and visit the pyramids.
Race underground or in space, watching the stars passing by. Race underground or in space, watching the stars pass by. Or rest under the
Have some rest under the palms on the beach (watching the other karts palm trees on the beach, watching the other karts overtake you. But don't eat
overtaking you :) ). the bananas! Watch for bowling balls, plungers, bubble gum and cakes thrown by
But don't eat the bananas! Watch for bowling balls, plungers, bubble gum your opponents.
and cakes thrown by opponents.
</p> </p>
<p> <p>
You can do a single race against other karts, compete in one of several You can do a single race against other karts, compete in one of several Grand
Grand Prix, try to beat the high score in time trials on your own, play Prix, try to beat the high score in time trials on your own, play battle mode
battle mode against your friends, and more! against the computer or your friends, and more!
</p> </p>
</description> </description>
<url type="homepage">http://supertuxkart.sourceforge.net/</url> <url type="homepage">http://supertuxkart.sourceforge.net/</url>
<screenshots> <screenshots>
<screenshot type="default">http://supertuxkart.sourceforge.net/persistent/images/4/4d/SuperTuxKart_0.8_screenshot.jpg</screenshot> <screenshot type="default">http://supertuxkart.sourceforge.net/persistent/images/4/4e/Supertuxkart-0.9-screenshot-2.jpg</screenshot>
<screenshot>http://supertuxkart.sourceforge.net/persistent/images/1/1f/SuperTuxKart_0.8_screenshot4.jpg</screenshot> <screenshot>http://supertuxkart.sourceforge.net/persistent/images/a/a9/Supertuxkart-0.9-screenshot-1.jpg</screenshot>
<screenshot>http://supertuxkart.sourceforge.net/persistent/images/6/63/Supertuxkart-0.9-screenshot-3.jpg</screenshot>
</screenshots> </screenshots>
<updatecontact>supertuxkart-devel@lists.sourceforge.net</updatecontact> <updatecontact>supertuxkart-devel@lists.sourceforge.net</updatecontact>
</application> </application>

View File

@@ -10,9 +10,9 @@ endif()
find_package(OpenGL REQUIRED) find_package(OpenGL REQUIRED)
include_directories(${OPENGL_INCLUDE_DIR}) include_directories(${OPENGL_INCLUDE_DIR})
add_definitions(-DGLEW_STATIC)
add_library(glew STATIC add_library(glew STATIC
include/GL/glew.h include/GL/glxew.h include/GL/wglew.h include/GL/glew.h include/GL/glxew.h include/GL/wglew.h
src/glew.c src/glewinfo.c src/glew.c src/glewinfo.c
) )
add_definitions(-DGLEW_STATIC)

View File

@@ -46,6 +46,7 @@ void CentralVideoSettings::init()
hasMultiDrawIndirect = false; hasMultiDrawIndirect = false;
hasTextureCompression = false; hasTextureCompression = false;
hasUBO = false; hasUBO = false;
hasExplicitAttribLocation = false;
hasGS = false; hasGS = false;
m_GI_has_artifact = false; m_GI_has_artifact = false;
@@ -154,11 +155,24 @@ void CentralVideoSettings::init()
hasUBO = true; hasUBO = true;
Log::info("GLDriver", "ARB Uniform Buffer Object Present"); Log::info("GLDriver", "ARB Uniform Buffer Object Present");
} }
if (!GraphicsRestrictions::isDisabled(GraphicsRestrictions::GR_GEOMETRY_SHADER4) && if (!GraphicsRestrictions::isDisabled(GraphicsRestrictions::GR_EXPLICIT_ATTRIB_LOCATION) &&
hasGLExtension("GL_ARB_explicit_attrib_location")) {
hasExplicitAttribLocation = true;
Log::info("GLDriver", "ARB Explicit Attrib Location Present");
}
#if defined(__linux__)
if (!GraphicsRestrictions::isDisabled(GraphicsRestrictions::GR_GEOMETRY_SHADER) &&
(m_gl_major_version > 3 || (m_gl_major_version == 3 && m_gl_minor_version >= 2))) {
hasGS = true;
Log::info("GLDriver", "Geometry Shaders Present");
}
#else
if (!GraphicsRestrictions::isDisabled(GraphicsRestrictions::GR_GEOMETRY_SHADER) &&
hasGLExtension("GL_ARB_geometry_shader4")) { hasGLExtension("GL_ARB_geometry_shader4")) {
hasGS = true; hasGS = true;
Log::info("GLDriver", "ARB Geometry Shader 4 Present"); Log::info("GLDriver", "ARB Geometry Shader 4 Present");
} }
#endif
// Only unset the high def textures if they are set as default. If the // Only unset the high def textures if they are set as default. If the
// user has enabled them (bit 1 set), then leave them enabled. // user has enabled them (bit 1 set), then leave them enabled.
@@ -229,7 +243,7 @@ bool CentralVideoSettings::needsSRGBCapableVisualWorkaround() const
return m_need_srgb_visual_workaround; return m_need_srgb_visual_workaround;
} }
bool CentralVideoSettings::isARBGeometryShader4Usable() const bool CentralVideoSettings::isARBGeometryShadersUsable() const
{ {
return hasGS; return hasGS;
} }
@@ -239,6 +253,11 @@ bool CentralVideoSettings::isARBUniformBufferObjectUsable() const
return hasUBO; return hasUBO;
} }
bool CentralVideoSettings::isARBExplicitAttribLocationUsable() const
{
return hasExplicitAttribLocation;
}
bool CentralVideoSettings::isEXTTextureCompressionS3TCUsable() const bool CentralVideoSettings::isEXTTextureCompressionS3TCUsable() const
{ {
return hasTextureCompression; return hasTextureCompression;
@@ -311,12 +330,12 @@ bool CentralVideoSettings::isARBMultiDrawIndirectUsable() const
bool CentralVideoSettings::supportsShadows() const bool CentralVideoSettings::supportsShadows() const
{ {
return isARBGeometryShader4Usable() && isARBUniformBufferObjectUsable(); return isARBGeometryShadersUsable() && isARBUniformBufferObjectUsable() && isARBExplicitAttribLocationUsable();
} }
bool CentralVideoSettings::supportsGlobalIllumination() const bool CentralVideoSettings::supportsGlobalIllumination() const
{ {
return isARBGeometryShader4Usable() && isARBUniformBufferObjectUsable() && !m_GI_has_artifact; return isARBGeometryShadersUsable() && isARBUniformBufferObjectUsable() && isARBExplicitAttribLocationUsable() && !m_GI_has_artifact;
} }
bool CentralVideoSettings::supportsIndirectInstancingRendering() const bool CentralVideoSettings::supportsIndirectInstancingRendering() const

View File

@@ -35,6 +35,7 @@ private:
bool hasTextureView; bool hasTextureView;
bool hasBindlessTexture; bool hasBindlessTexture;
bool hasUBO; bool hasUBO;
bool hasExplicitAttribLocation;
bool hasGS; bool hasGS;
bool hasTextureCompression; bool hasTextureCompression;
bool hasAtomics; bool hasAtomics;
@@ -60,7 +61,7 @@ public:
bool isARBUniformBufferObjectUsable() const; bool isARBUniformBufferObjectUsable() const;
bool isEXTTextureCompressionS3TCUsable() const; bool isEXTTextureCompressionS3TCUsable() const;
bool isARBTextureViewUsable() const; bool isARBTextureViewUsable() const;
bool isARBGeometryShader4Usable() const; bool isARBGeometryShadersUsable() const;
bool isARBTextureStorageUsable() const; bool isARBTextureStorageUsable() const;
bool isAMDVertexShaderLayerUsable() const; bool isAMDVertexShaderLayerUsable() const;
bool isARBComputeShaderUsable() const; bool isARBComputeShaderUsable() const;
@@ -73,6 +74,7 @@ public:
bool isARBShaderStorageBufferObjectUsable() const; bool isARBShaderStorageBufferObjectUsable() const;
bool isARBImageLoadStoreUsable() const; bool isARBImageLoadStoreUsable() const;
bool isARBMultiDrawIndirectUsable() const; bool isARBMultiDrawIndirectUsable() const;
bool isARBExplicitAttribLocationUsable() const;
// Are all required extensions available for feature support // Are all required extensions available for feature support

View File

@@ -41,7 +41,7 @@ namespace GraphicsRestrictions
const char *m_names_of_restrictions[] = { const char *m_names_of_restrictions[] = {
"UniformBufferObject", "UniformBufferObject",
"GeometryShader4", "GeometryShader",
"DrawIndirect", "DrawIndirect",
"TextureView", "TextureView",
"TextureStorage", "TextureStorage",
@@ -56,6 +56,7 @@ namespace GraphicsRestrictions
"BindlessTexture", "BindlessTexture",
"TextureCompressionS3TC", "TextureCompressionS3TC",
"AMDVertexShaderLayer", "AMDVertexShaderLayer",
"ExplicitAttribLocation",
"DriverRecentEnough", "DriverRecentEnough",
"HighDefinitionTextures", "HighDefinitionTextures",
"AdvancedPipeline", "AdvancedPipeline",

View File

@@ -35,7 +35,7 @@ namespace GraphicsRestrictions
enum GraphicsRestrictionsType enum GraphicsRestrictionsType
{ {
GR_UNIFORM_BUFFER_OBJECT, GR_UNIFORM_BUFFER_OBJECT,
GR_GEOMETRY_SHADER4, GR_GEOMETRY_SHADER,
GR_DRAW_INDIRECT, GR_DRAW_INDIRECT,
GR_TEXTURE_VIEW, GR_TEXTURE_VIEW,
GR_TEXTURE_STORAGE, GR_TEXTURE_STORAGE,
@@ -50,6 +50,7 @@ namespace GraphicsRestrictions
GR_BINDLESS_TEXTURE, GR_BINDLESS_TEXTURE,
GR_EXT_TEXTURE_COMPRESSION_S3TC, GR_EXT_TEXTURE_COMPRESSION_S3TC,
GR_AMD_VERTEX_SHADER_LAYER, GR_AMD_VERTEX_SHADER_LAYER,
GR_EXPLICIT_ATTRIB_LOCATION,
GR_DRIVER_RECENT_ENOUGH, GR_DRIVER_RECENT_ENOUGH,
GR_HIGHDEFINITION_TEXTURES, GR_HIGHDEFINITION_TEXTURES,
GR_ADVANCED_PIPELINE, GR_ADVANCED_PIPELINE,

View File

@@ -674,7 +674,7 @@ void IrrDriver::renderGlow(std::vector<GlowData>& glows)
node->render(); node->render();
} }
if (CVS->supportsIndirectInstancingRendering()) if (CVS->supportsIndirectInstancingRendering() && CVS->isARBExplicitAttribLocationUsable())
{ {
glBindBuffer(GL_DRAW_INDIRECT_BUFFER, GlowPassCmd::getInstance()->drawindirectcmd); glBindBuffer(GL_DRAW_INDIRECT_BUFFER, GlowPassCmd::getInstance()->drawindirectcmd);
InstancedColorizeShader::getInstance()->use(); InstancedColorizeShader::getInstance()->use();

View File

@@ -84,6 +84,9 @@ GLuint ShaderBase::loadShader(const std::string &file, unsigned type)
if (CVS->isAMDVertexShaderLayerUsable()) if (CVS->isAMDVertexShaderLayerUsable())
code << "#extension GL_AMD_vertex_shader_layer : enable\n"; code << "#extension GL_AMD_vertex_shader_layer : enable\n";
if (CVS->isARBExplicitAttribLocationUsable())
code << "#extension GL_ARB_explicit_attrib_location : enable\n";
if (CVS->isAZDOEnabled()) if (CVS->isAZDOEnabled())
{ {
code << "#extension GL_ARB_bindless_texture : enable\n"; code << "#extension GL_ARB_bindless_texture : enable\n";

View File

@@ -299,6 +299,7 @@ void Skybox::generateSpecularCubemap()
} }
glBindFramebuffer(GL_FRAMEBUFFER, 0); glBindFramebuffer(GL_FRAMEBUFFER, 0);
glDeleteFramebuffers(1, &fbo); glDeleteFramebuffers(1, &fbo);
glActiveTexture(GL_TEXTURE0);
} // generateSpecularCubemap } // generateSpecularCubemap

View File

@@ -419,8 +419,7 @@ void initTexturesTransparent(GLMesh &mesh)
{ {
if (!mesh.textures[0]) if (!mesh.textures[0])
{ {
Log::fatal("STKMesh", "Missing texture for material transparent"); mesh.textures[0] = getUnicolorTexture(video::SColor(255, 255, 255, 255));
return;
} }
compressTexture(mesh.textures[0], true); compressTexture(mesh.textures[0], true);
if (CVS->isAZDOEnabled()) if (CVS->isAZDOEnabled())

View File

@@ -532,10 +532,9 @@ bool ItemManager::randomItemsForArena(const AlignedArray<btTransform>& pos)
for (unsigned int j = 0; j < used_location.size(); j++) for (unsigned int j = 0; j < used_location.size(); j++)
{ {
if (!found) continue; if (!found) continue;
Vec3 d = BattleGraph::get() float test_distance = BattleGraph::get()
->getPolyOfNode(used_location[j]).getCenter() - ->getDistance(used_location[j], node);
BattleGraph::get()->getPolyOfNode(node).getCenter(); found = test_distance > MIN_DIST;
found = d.length_2d() > MIN_DIST;
} }
if (found) if (found)
{ {

View File

@@ -283,23 +283,24 @@ void AIBaseController::crashed(const Material *m)
} // crashed(Material) } // crashed(Material)
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void AIBaseController::checkPosition(const Vec3 &point, void AIBaseController::checkPosition(const Vec3 &point, posData *pos_data,
posData *pos_data, Vec3 *lc, bool use_front_xyz) const
Vec3 *lc) const
{ {
// Convert to local coordinates from the point of view of current kart // Convert to local coordinates from the point of view of current kart
btQuaternion q(btVector3(0, 1, 0), -m_kart->getHeading()); btQuaternion q(btVector3(0, 1, 0), -m_kart->getHeading());
Vec3 p = point - m_kart->getXYZ(); Vec3 p = point -
(use_front_xyz ? m_kart->getFrontXYZ() : m_kart->getXYZ());
Vec3 local_coordinates = quatRotate(q, p); Vec3 local_coordinates = quatRotate(q, p);
// Save local coordinates for later use if needed // Save local coordinates for later use if needed
if (lc) *lc = local_coordinates; if (lc) *lc = local_coordinates;
// on_side: tell whether it's left or right hand side if (pos_data == NULL) return;
// lhs: tell whether it's left or right hand side
if (local_coordinates.getX() < 0) if (local_coordinates.getX() < 0)
pos_data->on_side = true; pos_data->lhs = true;
else else
pos_data->on_side = false; pos_data->lhs = false;
// behind: tell whether it's behind or not // behind: tell whether it's behind or not
if (local_coordinates.getZ() < 0) if (local_coordinates.getZ() < 0)
@@ -309,6 +310,6 @@ void AIBaseController::checkPosition(const Vec3 &point,
pos_data->angle = atan2(fabsf(local_coordinates.getX()), pos_data->angle = atan2(fabsf(local_coordinates.getX()),
fabsf(local_coordinates.getZ())); fabsf(local_coordinates.getZ()));
pos_data->distance = p.length_2d(); pos_data->distance = p.length();
} // checkPosition } // checkPosition

View File

@@ -65,7 +65,7 @@ protected:
static int m_test_ai; static int m_test_ai;
/** Position info structure of targets. */ /** Position info structure of targets. */
struct posData {bool behind; bool on_side; float angle; float distance;}; struct posData {bool behind; bool lhs; float angle; float distance;};
void setControllerName(const std::string &name); void setControllerName(const std::string &name);
float steerToPoint(const Vec3 &point); float steerToPoint(const Vec3 &point);
@@ -77,7 +77,9 @@ protected:
/** This can be called to detect if the kart is stuck (i.e. repeatedly /** This can be called to detect if the kart is stuck (i.e. repeatedly
* hitting part of the track). */ * hitting part of the track). */
bool isStuck() const { return m_stuck; } bool isStuck() const { return m_stuck; }
void checkPosition(const Vec3&, posData*, Vec3* lc = NULL) const; void checkPosition(const Vec3&, posData*,
Vec3* lc = NULL,
bool use_front_xyz = false) const;
public: public:
AIBaseController(AbstractKart *kart); AIBaseController(AbstractKart *kart);

View File

@@ -29,10 +29,20 @@
#include "tracks/battle_graph.hpp" #include "tracks/battle_graph.hpp"
#include "utils/log.hpp" #include "utils/log.hpp"
int ArenaAI::m_test_node_for_banana = BattleGraph::UNKNOWN_POLY;
bool isNodeWithBanana(const std::pair<const Item*, int>& item_pair)
{
return item_pair.second == ArenaAI::m_test_node_for_banana &&
item_pair.first->getType() == Item::ITEM_BANANA &&
!item_pair.first->wasCollected();
}
ArenaAI::ArenaAI(AbstractKart *kart) ArenaAI::ArenaAI(AbstractKart *kart)
: AIBaseController(kart) : AIBaseController(kart)
{ {
m_debug_sphere = NULL; m_debug_sphere = NULL;
m_debug_sphere_next = NULL;
} // ArenaAI } // ArenaAI
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@@ -41,6 +51,8 @@ ArenaAI::ArenaAI(AbstractKart *kart)
void ArenaAI::reset() void ArenaAI::reset()
{ {
m_target_node = BattleGraph::UNKNOWN_POLY; m_target_node = BattleGraph::UNKNOWN_POLY;
m_current_forward_node = BattleGraph::UNKNOWN_POLY;
m_current_forward_point = Vec3(0, 0, 0);
m_adjusting_side = false; m_adjusting_side = false;
m_closest_kart = NULL; m_closest_kart = NULL;
m_closest_kart_node = BattleGraph::UNKNOWN_POLY; m_closest_kart_node = BattleGraph::UNKNOWN_POLY;
@@ -49,14 +61,17 @@ void ArenaAI::reset()
m_cur_kart_pos_data = {0}; m_cur_kart_pos_data = {0};
m_is_stuck = false; m_is_stuck = false;
m_is_uturn = false; m_is_uturn = false;
m_avoiding_banana = false;
m_target_point = Vec3(0, 0, 0); m_target_point = Vec3(0, 0, 0);
m_time_since_last_shot = 0.0f; m_time_since_last_shot = 0.0f;
m_time_since_driving = 0.0f; m_time_since_driving = 0.0f;
m_time_since_reversing = 0.0f; m_time_since_reversing = 0.0f;
m_time_since_uturn = 0.0f; m_time_since_uturn = 0.0f;
m_turn_radius = 0.0f;
m_turn_angle = 0.0f;
m_on_node.clear(); m_on_node.clear();
m_path_corners.clear(); m_aiming_points.clear();
m_portals.clear(); m_aiming_nodes.clear();
m_cur_difficulty = race_manager->getDifficulty(); m_cur_difficulty = race_manager->getDifficulty();
AIBaseController::reset(); AIBaseController::reset();
@@ -72,10 +87,14 @@ void ArenaAI::update(float dt)
// This is used to enable firing an item backwards. // This is used to enable firing an item backwards.
m_controls->m_look_back = false; m_controls->m_look_back = false;
m_controls->m_nitro = false; m_controls->m_nitro = false;
m_avoiding_banana = false;
// Don't do anything if there is currently a kart animations shown. // Don't do anything if there is currently a kart animations shown.
if (m_kart->getKartAnimation()) if (m_kart->getKartAnimation())
{
resetAfterStop();
return; return;
}
if (isWaiting()) if (isWaiting())
{ {
@@ -90,16 +109,16 @@ void ArenaAI::update(float dt)
findClosestKart(true); findClosestKart(true);
findTarget(); findTarget();
handleArenaItems(dt); handleArenaItems(dt);
handleArenaBanana();
if (m_kart->getSpeed() > 15.0f && m_cur_kart_pos_data.angle < 0.2f) if (m_kart->getSpeed() > 15.0f && m_turn_angle < 20)
{ {
// Only use nitro when target is straight // Only use nitro when turn angle is big (180 - angle)
m_controls->m_nitro = true; m_controls->m_nitro = true;
} }
if (m_is_uturn) if (m_is_uturn)
{ {
resetAfterStop();
handleArenaUTurn(dt); handleArenaUTurn(dt);
} }
else else
@@ -113,6 +132,129 @@ void ArenaAI::update(float dt)
} // update } // update
//-----------------------------------------------------------------------------
bool ArenaAI::updateAimingPosition()
{
// Notice: we use the point ahead of kart to determine next node,
// to compensate the time difference between steering
m_current_forward_point =
m_kart->getTrans()(Vec3(0, 0, m_kart->getKartLength()));
m_current_forward_node = BattleGraph::get()->pointToNode
(m_current_forward_node, m_current_forward_point,
false/*ignore_vertical*/);
// Use current node if forward node is unknown, or near the target
const int forward = (m_current_forward_node == BattleGraph::UNKNOWN_POLY ||
m_current_forward_node == m_target_node ||
getCurrentNode() == m_target_node ? getCurrentNode() :
m_current_forward_node);
if (forward == BattleGraph::UNKNOWN_POLY ||
m_target_node == BattleGraph::UNKNOWN_POLY)
return false;
if (forward == m_target_node)
{
m_aiming_points.push_back(BattleGraph::get()
->getPolyOfNode(forward).getCenter());
m_aiming_points.push_back(m_target_point);
m_aiming_nodes.insert(forward);
m_aiming_nodes.insert(getCurrentNode());
return true;
}
const int next_node = BattleGraph::get()
->getNextShortestPathPoly(forward, m_target_node);
if (next_node == BattleGraph::UNKNOWN_POLY)
{
Log::error("ArenaAI", "Next node is unknown, did you forget to link"
"adjacent face in navmesh?");
return false;
}
m_aiming_points.push_back(BattleGraph::get()
->getPolyOfNode(forward).getCenter());
m_aiming_points.push_back(BattleGraph::get()
->getPolyOfNode(next_node).getCenter());
m_aiming_nodes.insert(forward);
m_aiming_nodes.insert(next_node);
m_aiming_nodes.insert(getCurrentNode());
return true;
} // updateAimingPosition
//-----------------------------------------------------------------------------
/** This function sets the steering.
* \param dt Time step size.
*/
void ArenaAI::handleArenaSteering(const float dt)
{
const int current_node = getCurrentNode();
if (current_node == BattleGraph::UNKNOWN_POLY ||
m_target_node == BattleGraph::UNKNOWN_POLY)
{
return;
}
m_aiming_points.clear();
m_aiming_nodes.clear();
const bool found_position = updateAimingPosition();
if (ignorePathFinding())
{
// Steer directly
checkPosition(m_target_point, &m_cur_kart_pos_data);
#ifdef AI_DEBUG
m_debug_sphere->setPosition(m_target_point.toIrrVector());
#endif
if (m_cur_kart_pos_data.behind)
{
m_adjusting_side = m_cur_kart_pos_data.lhs;
m_is_uturn = true;
}
else
{
float target_angle = steerToPoint(m_target_point);
setSteering(target_angle, dt);
}
return;
}
else if (found_position)
{
updateBananaLocation();
assert(m_aiming_points.size() == 2);
updateTurnRadius(m_kart->getXYZ(), m_aiming_points[0],
m_aiming_points[1]);
m_target_point = m_aiming_points[1];
checkPosition(m_target_point, &m_cur_kart_pos_data);
#ifdef AI_DEBUG
m_debug_sphere->setVisible(true);
m_debug_sphere_next->setVisible(true);
m_debug_sphere->setPosition(m_aiming_points[0].toIrrVector());
m_debug_sphere_next->setPosition(m_aiming_points[1].toIrrVector());
#endif
if (m_cur_kart_pos_data.behind)
{
m_adjusting_side = m_cur_kart_pos_data.lhs;
m_is_uturn = true;
}
else
{
float target_angle = steerToPoint(m_target_point);
setSteering(target_angle, dt);
}
return;
}
else
{
// Do nothing (go straight) if no targets found
setSteering(0.0f, dt);
return;
}
} // handleSteering
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void ArenaAI::checkIfStuck(const float dt) void ArenaAI::checkIfStuck(const float dt)
{ {
@@ -154,6 +296,7 @@ void ArenaAI::checkIfStuck(const float dt)
*/ */
void ArenaAI::handleArenaAcceleration(const float dt) void ArenaAI::handleArenaAcceleration(const float dt)
{ {
if (m_controls->m_brake) if (m_controls->m_brake)
{ {
m_controls->m_accel = 0.0f; m_controls->m_accel = 0.0f;
@@ -173,7 +316,7 @@ void ArenaAI::handleArenaUTurn(const float dt)
if (fabsf(m_kart->getSpeed()) > if (fabsf(m_kart->getSpeed()) >
(m_kart->getKartProperties()->getEngineMaxSpeed() / 5) (m_kart->getKartProperties()->getEngineMaxSpeed() / 5)
&& m_kart->getSpeed() < 0) // Try to emulate reverse like human players && m_kart->getSpeed() < 0) // Try to emulate reverse like human players
m_controls->m_accel = -0.06f; m_controls->m_accel = -0.06f;
else else
m_controls->m_accel = -5.0f; m_controls->m_accel = -5.0f;
@@ -201,6 +344,7 @@ bool ArenaAI::handleArenaUnstuck(const float dt)
{ {
if (!m_is_stuck || m_is_uturn) return false; if (!m_is_stuck || m_is_uturn) return false;
resetAfterStop();
setSteering(0.0f, dt); setSteering(0.0f, dt);
if (fabsf(m_kart->getSpeed()) > if (fabsf(m_kart->getSpeed()) >
@@ -223,287 +367,76 @@ bool ArenaAI::handleArenaUnstuck(const float dt)
} // handleArenaUnstuck } // handleArenaUnstuck
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
/** This function sets the steering. void ArenaAI::updateBananaLocation()
* \param dt Time step size.
*/
void ArenaAI::handleArenaSteering(const float dt)
{ {
const int current_node = getCurrentNode(); std::vector<std::pair<const Item*, int>>& item_list =
if (current_node == BattleGraph::UNKNOWN_POLY ||
m_target_node == BattleGraph::UNKNOWN_POLY) return;
if (m_target_node == current_node)
{
// Very close to the item, steer directly
checkPosition(m_target_point, &m_cur_kart_pos_data);
#ifdef AI_DEBUG
m_debug_sphere->setPosition(m_target_point.toIrrVector());
#endif
if (m_cur_kart_pos_data.behind)
{
m_adjusting_side = m_cur_kart_pos_data.on_side;
m_is_uturn = true;
}
else
{
float target_angle = steerToPoint(m_target_point);
setSteering(target_angle, dt);
}
return;
}
else if (m_target_node != current_node)
{
findPortals(current_node, m_target_node);
stringPull(m_kart->getXYZ(), m_target_point);
if (m_path_corners.size() > 0)
m_target_point = m_path_corners[0];
checkPosition(m_target_point, &m_cur_kart_pos_data);
#ifdef AI_DEBUG
m_debug_sphere->setPosition(m_target_point.toIrrVector());
#endif
if (m_cur_kart_pos_data.behind)
{
m_adjusting_side = m_cur_kart_pos_data.on_side;
m_is_uturn = true;
}
else
{
float target_angle = steerToPoint(m_target_point);
setSteering(target_angle, dt);
}
return;
}
else
{
// Do nothing (go straight) if no targets found
setSteering(0.0f, dt);
return;
}
} // handleSteering
//-----------------------------------------------------------------------------
void ArenaAI::handleArenaBanana()
{
if (m_is_uturn) return;
const std::vector< std::pair<const Item*, int> >& item_list =
BattleGraph::get()->getItemList(); BattleGraph::get()->getItemList();
const unsigned int items_count = item_list.size();
for (unsigned int i = 0; i < items_count; ++i) std::set<int>::iterator node = m_aiming_nodes.begin();
while (node != m_aiming_nodes.end())
{ {
const Item* item = item_list[i].first; m_test_node_for_banana = *node;
if (item->getType() == Item::ITEM_BANANA && !item->wasCollected()) std::vector<std::pair<const Item*, int>>::iterator it =
std::find_if(item_list.begin(), item_list.end(), isNodeWithBanana);
if (it != item_list.end())
{ {
posData banana_pos = {0}; Vec3 banana_lc;
Vec3 banana_lc(0, 0, 0); checkPosition(it->first->getXYZ(), NULL, &banana_lc,
checkPosition(item->getXYZ(), &banana_pos, &banana_lc); true/*use_front_xyz*/);
if (banana_pos.angle < 0.2f && banana_pos.distance < 7.5f &&
!banana_pos.behind) // If satisfy the below condition, AI should not eat banana:
// banana_lc.z() < 0.0f, behind the kart
if (banana_lc.z() < 0.0f)
{ {
// Check whether it's straight ahead towards a banana node++;
// If so, adjust target point
banana_lc = (banana_pos.on_side ? banana_lc + Vec3 (2, 0, 0) :
banana_lc - Vec3 (2, 0, 0));
m_target_point = m_kart->getTrans()(banana_lc);
m_target_node = BattleGraph::get()
->pointToNode(getCurrentNode(), m_target_point,
false/*ignore_vertical*/);
// Handle one banana only
break;
}
}
}
} // handleArenaBanana
//-----------------------------------------------------------------------------
/** This function finds the polyon edges(portals) that the AI will cross before
* reaching its destination. We start from the current polygon and call
* BattleGraph::getNextShortestPathPoly() to find the next polygon on the shortest
* path to the destination. Then find the common edge between the current
* poly and the next poly, store it and step through the channel.
*
* 1----2----3 In this case, the portals are:
* |strt| | (2,5) (4,5) (10,7) (10,9) (11,12)
* 6----5----4
* | |
* 7----10----11----14
* | | | end |
* 8----9-----12----13
*
* \param start The start node(polygon) of the channel.
* \param end The end node(polygon) of the channel.
*/
void ArenaAI::findPortals(int start, int end)
{
int this_node = start;
// We can't use NULL because NULL==0 which is a valid node, so we initialize
// with a value that is always invalid.
int next_node = -999;
m_portals.clear();
while (next_node != end && this_node != -1 && next_node != -1 && this_node != end)
{
next_node = BattleGraph::get()->getNextShortestPathPoly(this_node, end);
if (next_node == BattleGraph::UNKNOWN_POLY || next_node == -999) return;
std::vector<int> this_node_verts =
NavMesh::get()->getNavPoly(this_node).getVerticesIndex();
std::vector<int> next_node_verts=
NavMesh::get()->getNavPoly(next_node).getVerticesIndex();
// this_node_verts and next_node_verts hold vertices of polygons in CCW order
// We reverse next_node_verts so it becomes easy to compare edges in the next step
std::reverse(next_node_verts.begin(),next_node_verts.end());
Vec3 portalLeft, portalRight;
//bool flag = 0;
for (unsigned int n_i = 0; n_i < next_node_verts.size(); n_i++)
{
for (unsigned int t_i = 0; t_i < this_node_verts.size(); t_i++)
{
if ((next_node_verts[n_i] == this_node_verts[t_i]) &&
(next_node_verts[(n_i+1)%next_node_verts.size()] ==
this_node_verts[(t_i+1)%this_node_verts.size()]))
{
portalLeft = NavMesh::get()->
getVertex(this_node_verts[(t_i+1)%this_node_verts.size()]);
portalRight = NavMesh::get()->getVertex(this_node_verts[t_i]);
}
}
}
m_portals.push_back(std::make_pair(portalLeft, portalRight));
// for debugging:
//m_debug_sphere->setPosition((portalLeft).toIrrVector());
this_node = next_node;
}
} // findPortals
//-----------------------------------------------------------------------------
/** This function implements the funnel algorithm for finding shortest paths
* through a polygon channel. This means that we should move from corner to
* corner to move on the most straight and shortest path to the destination.
* This can be visualized as pulling a string from the end point to the start.
* The string will bend at the corners, and this algorithm will find those
* corners using portals from findPortals(). The AI will aim at the first
* corner and the rest can be used for estimating the curve (braking).
*
* 1----2----3 In this case, the corners are:
* |strt| | <5,10,end>
* 6----5----4
* | |
* 7----10----11----14
* | | | end |
* 8----9-----12----13
*
* \param start_pos The start position (usually the AI's current position).
* \param end_pos The end position (m_target_point).
*/
void ArenaAI::stringPull(const Vec3& start_pos, const Vec3& end_pos)
{
Vec3 funnel_apex = start_pos;
Vec3 funnel_left = m_portals[0].first;
Vec3 funnel_right = m_portals[0].second;
unsigned int apex_index=0, fun_left_index=0, fun_right_index=0;
m_portals.push_back(std::make_pair(end_pos, end_pos));
m_path_corners.clear();
const float eps=0.0001f;
for (unsigned int i = 0; i < m_portals.size(); i++)
{
Vec3 portal_left = m_portals[i].first;
Vec3 portal_right = m_portals[i].second;
//Compute for left edge
if ((funnel_left == funnel_apex) ||
portal_left.sideOfLine2D(funnel_apex, funnel_left) <= -eps)
{
funnel_left = 0.98f*portal_left + 0.02f*portal_right;
//funnel_left = portal_left;
fun_left_index = i;
if (portal_left.sideOfLine2D(funnel_apex, funnel_right) < -eps)
{
funnel_apex = funnel_right;
apex_index = fun_right_index;
m_path_corners.push_back(funnel_apex);
funnel_left = funnel_apex;
funnel_right = funnel_apex;
i = apex_index;
continue; continue;
} }
// If the node AI will pass has a banana, adjust the aim position
banana_lc = (banana_lc.x() < 0 ? banana_lc + Vec3(5, 0, 0) :
banana_lc - Vec3(5, 0, 0));
m_aiming_points[1] = m_kart->getTrans()(banana_lc);
m_avoiding_banana = true;
// Handle one banana only
return;
} }
node++;
//Compute for right edge
if ((funnel_right == funnel_apex) ||
portal_right.sideOfLine2D(funnel_apex, funnel_right) >= eps)
{
funnel_right = 0.98f*portal_right + 0.02f*portal_left;
//funnel_right = portal_right;
fun_right_index = i;
if (portal_right.sideOfLine2D(funnel_apex, funnel_left) > eps)
{
funnel_apex = funnel_left;
apex_index = fun_left_index;
m_path_corners.push_back(funnel_apex);
funnel_left = funnel_apex;
funnel_right = funnel_apex;
i = apex_index;
continue;
}
}
} }
//Push end_pos to m_path_corners so if no corners, we aim at target } // updateBananaLocation
m_path_corners.push_back(end_pos);
} // stringPull
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
/** This function handles braking. It calls determineTurnRadius() to find out /** This function handles braking. It used the turn radius found by
* the curve radius. Depending on the turn radius, it finds out the maximum * updateTurnRadius(). Depending on the turn radius, it finds out the maximum
* speed. If the current speed is greater than the max speed and a set minimum * speed. If the current speed is greater than the max speed and a set minimum
* speed, brakes are applied. * speed, brakes are applied.
*/ */
void ArenaAI::handleArenaBraking() void ArenaAI::handleArenaBraking()
{ {
m_controls->m_brake = false;
if (getCurrentNode() == BattleGraph::UNKNOWN_POLY ||
m_target_node == BattleGraph::UNKNOWN_POLY) return;
// A kart will not brake when the speed is already slower than this // A kart will not brake when the speed is already slower than this
// value. This prevents a kart from going too slow (or even backwards) // value. This prevents a kart from going too slow (or even backwards)
// in tight curves. // in tight curves.
const float MIN_SPEED = 5.0f; const float MIN_SPEED = 5.0f;
std::vector<Vec3> points; if (forceBraking() && m_kart->getSpeed() > MIN_SPEED)
{
// Brake now
m_controls->m_brake = true;
return;
}
points.push_back(m_kart->getXYZ()); m_controls->m_brake = false;
points.push_back(m_path_corners[0]);
points.push_back((m_path_corners.size()>=2) ? m_path_corners[1] : m_path_corners[0]);
float current_curve_radius = determineTurnRadius(points); if (getCurrentNode() == BattleGraph::UNKNOWN_POLY ||
m_target_node == BattleGraph::UNKNOWN_POLY) return;
Vec3 d1 = m_kart->getXYZ() - m_target_point; if (m_aiming_points.empty()) return;
Vec3 d2 = m_kart->getXYZ() - m_path_corners[0];
if (d1.length2_2d() < d2.length2_2d())
current_curve_radius = d1.length_2d();
float max_turn_speed = m_kart->getSpeedForTurnRadius(current_curve_radius); const float max_turn_speed = m_kart->getSpeedForTurnRadius(m_turn_radius);
if (m_kart->getSpeed() > max_turn_speed && if (m_kart->getSpeed() > 1.25f * max_turn_speed &&
fabsf(m_controls->m_steer) > 0.95f &&
m_kart->getSpeed() > MIN_SPEED) m_kart->getSpeed() > MIN_SPEED)
{ {
m_controls->m_brake = true; m_controls->m_brake = true;
@@ -512,60 +445,58 @@ void ArenaAI::handleArenaBraking()
} // handleArenaBraking } // handleArenaBraking
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
/** The turn radius is determined by fitting a parabola to 3 points: current void ArenaAI::updateTurnRadius(const Vec3& p1, const Vec3& p2,
* location of AI, first corner and the second corner. Once the constants are const Vec3& p3)
* computed, a formula is used to find the radius of curvature at the kart's
* current location.
* NOTE: This method does not apply enough braking, should think of something
* else.
*/
float ArenaAI::determineTurnRadius( std::vector<Vec3>& points )
{ {
// Declaring variables // First use cosine formula to find out the angle made by the distance
float a, b; // between kart (point one) to point two and point two between point three
irr::core::CMatrix4<float> A; const float a = (p1 - p2).length();
irr::core::CMatrix4<float> X; const float b = (p2 - p3).length();
irr::core::CMatrix4<float> B; const float c = (p1 - p3).length();
const float angle = 180 - findAngleFrom3Edges(a, b, c);
//Populating matrices // Only calculate radius if not almost straight line
for (unsigned int i = 0; i < 3; i++) if (angle > 1 && angle < 179)
{ {
A(i, 0) = points[i].x()*points[i].x(); // angle
A(i, 1) = points[i].x(); // ^
A(i, 2) = 1.0f; // a / \ b
A(i, 3) = 0.0f; // 90/\ /\90
// \ / \ /
// \ /
// \ /
// \ /
// |
// Try to estimate the turn radius with the help of a kite-like
// polygon as shown, find out the lowest angle which is
// (4 - 2) * 180 - 90 - 90 - angle (180 - angle from above)
// Then we use this value as the angle of a sector of circle,
// a + b as the arc length, then the radius can be calculated easily
m_turn_radius = ((a + b) / (angle / 360)) / M_PI / 2;
} }
A(3, 0) = A(3, 1) = A(3, 2) = 0.0f; else
A(3, 3) = 1.0f;
for (unsigned int i = 0; i < 3; i++)
{ {
B(i, 0) = points[i].z(); // Return large radius so no braking is needed otherwise
B(i, 1) = 0.0f; m_turn_radius = 45.0f;
B(i, 2) = 0.0f;
B(i, 3) = 0.0f;
} }
B(3, 0) = B(3, 1) = B(3, 2) = B(3, 3) = 0.0f; m_turn_angle = angle;
//Computing inverse : X = inv(A)*B } // updateTurnRadius
irr::core::CMatrix4<float> invA;
if (!A.getInverse(invA))
return -1;
X = invA*B; //-----------------------------------------------------------------------------
a = X(0, 0); float ArenaAI::findAngleFrom3Edges(float a, float b, float c)
b = X(0, 1); {
//c = X(0, 2); // Cosine forumla : c2 = a2 + b2 - 2ab cos C
float test_value = ((c * c) - (a * a) - (b * b)) / (-(2 * a * b));
// Prevent error
if (test_value < -1)
test_value = -1;
else if (test_value > 1)
test_value = 1;
float x = points.front().x(); return acosf(test_value) * RAD_TO_DEGREE;
//float z = a*pow(x, 2) + b*x + c;
float dx_by_dz = 2*a*x + b;
float d2x_by_dz = 2*a;
float radius = pow(abs(1 + pow(dx_by_dz, 2)), 1.5f)/ abs(d2x_by_dz); } // findAngleFrom3Edges
return radius;
} // determineTurnRadius
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void ArenaAI::handleArenaItems(const float dt) void ArenaAI::handleArenaItems(const float dt)
@@ -663,7 +594,8 @@ void ArenaAI::handleArenaItems(const float dt)
if (m_time_since_last_shot < 1.0f) break; if (m_time_since_last_shot < 1.0f) break;
if (m_closest_kart_pos_data.distance < 6.0f && if (m_closest_kart_pos_data.distance < 6.0f &&
(difficulty || perfect_aim)) (difficulty || perfect_aim) &&
!m_closest_kart->isInvulnerable())
{ {
m_controls->m_fire = true; m_controls->m_fire = true;
m_controls->m_look_back = fire_behind; m_controls->m_look_back = fire_behind;
@@ -755,14 +687,15 @@ void ArenaAI::collectItemInArena(Vec3* aim_point, int* target_node) const
m_kart->getKartProperties()->getNitroSmallContainer())) m_kart->getKartProperties()->getNitroSmallContainer()))
continue; // Ignore nitro when already has some continue; // Ignore nitro when already has some
Vec3 d = item->getXYZ() - m_kart->getXYZ(); float test_distance = BattleGraph::get()
if (d.length_2d() <= distance && ->getDistance(item_list[i].second, getCurrentNode());
if (test_distance <= distance &&
(item->getType() == Item::ITEM_BONUS_BOX || (item->getType() == Item::ITEM_BONUS_BOX ||
item->getType() == Item::ITEM_NITRO_BIG || item->getType() == Item::ITEM_NITRO_BIG ||
item->getType() == Item::ITEM_NITRO_SMALL)) item->getType() == Item::ITEM_NITRO_SMALL))
{ {
closest_item_num = i; closest_item_num = i;
distance = d.length_2d(); distance = test_distance;
} }
} }

View File

@@ -56,6 +56,7 @@ protected:
/** For debugging purpose: a sphere indicating where the AI /** For debugging purpose: a sphere indicating where the AI
* is targeting at. */ * is targeting at. */
irr::scene::ISceneNode *m_debug_sphere; irr::scene::ISceneNode *m_debug_sphere;
irr::scene::ISceneNode *m_debug_sphere_next;
/** The node(poly) at which the target point lies in. */ /** The node(poly) at which the target point lies in. */
int m_target_node; int m_target_node;
@@ -63,7 +64,10 @@ protected:
/** The target point. */ /** The target point. */
Vec3 m_target_point; Vec3 m_target_point;
void collectItemInArena(Vec3*, int*) const; bool m_avoiding_banana;
void collectItemInArena(Vec3*, int*) const;
float findAngleFrom3Edges(float a, float b, float c);
private: private:
/** Used by handleArenaUTurn, it tells whether to do left or right /** Used by handleArenaUTurn, it tells whether to do left or right
* turning when steering is overridden. */ * turning when steering is overridden. */
@@ -81,15 +85,7 @@ private:
/** Holds the unique node ai has driven through, useful to tell if AI is /** Holds the unique node ai has driven through, useful to tell if AI is
* stuck by determine the size of this set. */ * stuck by determine the size of this set. */
std::set <int> m_on_node; std::set<int> m_on_node;
/** Holds the corner points computed using the funnel algorithm that the AI
* will eventaully move through. See stringPull(). */
std::vector<Vec3> m_path_corners;
/** Holds the set of portals that the kart will cross when moving through
* polygon channel. See findPortals(). */
std::vector<std::pair<Vec3,Vec3> > m_portals;
/** Time an item has been collected and not used. */ /** Time an item has been collected and not used. */
float m_time_since_last_shot; float m_time_since_last_shot;
@@ -103,22 +99,35 @@ private:
/** This is a timer that counts down when the kart is doing u-turn. */ /** This is a timer that counts down when the kart is doing u-turn. */
float m_time_since_uturn; float m_time_since_uturn;
float m_turn_radius;
float m_turn_angle;
Vec3 m_current_forward_point;
int m_current_forward_node;
std::set<int> m_aiming_nodes;
std::vector<Vec3> m_aiming_points;
void checkIfStuck(const float dt); void checkIfStuck(const float dt);
float determineTurnRadius(std::vector<Vec3>& points);
void findPortals(int start, int end);
void handleArenaAcceleration(const float dt); void handleArenaAcceleration(const float dt);
void handleArenaBanana();
void handleArenaBraking(); void handleArenaBraking();
void handleArenaItems(const float dt); void handleArenaItems(const float dt);
void handleArenaSteering(const float dt); void handleArenaSteering(const float dt);
void handleArenaUTurn(const float dt); void handleArenaUTurn(const float dt);
bool handleArenaUnstuck(const float dt); bool handleArenaUnstuck(const float dt);
void stringPull(const Vec3&, const Vec3&); bool updateAimingPosition();
void updateBananaLocation();
void updateTurnRadius(const Vec3& p1, const Vec3& p2,
const Vec3& p3);
virtual int getCurrentNode() const = 0; virtual int getCurrentNode() const = 0;
virtual bool isWaiting() const = 0; virtual bool isWaiting() const = 0;
virtual void resetAfterStop() {};
virtual void findClosestKart(bool use_difficulty) = 0; virtual void findClosestKart(bool use_difficulty) = 0;
virtual void findTarget() = 0; virtual void findTarget() = 0;
virtual bool forceBraking() { return m_avoiding_banana; }
virtual bool ignorePathFinding() { return false; }
public: public:
static int m_test_node_for_banana;
ArenaAI(AbstractKart *kart); ArenaAI(AbstractKart *kart);
virtual ~ArenaAI() {}; virtual ~ArenaAI() {};
virtual void update (float delta); virtual void update (float delta);

Some files were not shown because too many files have changed in this diff Show More