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
* Battle mode AI by Benau
* Soccer mode AI by Benau
* New icy soccer field by samuncle and Benau
* New subsea track by samuncle
* New volcano track by Ponzino
* TTF font rendering by Benau
* Kart properties refactor by Flakebi
* Scripting work under the hood
* Work on the track editor by mhp
* Tweak to challenges
* New farm track song by 0zone0ne and Krobonil
* Bugfixes
## SuperTuxKart 0.9.1

View File

@@ -1,6 +1,6 @@
# root CMakeLists for the SuperTuxKart project
project(SuperTuxKart)
set(PROJECT_VERSION "0.9.1")
set(PROJECT_VERSION "0.9.2")
cmake_minimum_required(VERSION 2.8.4)
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")
# Build glew library
add_definitions(-DGLEW_NO_GLU)
add_subdirectory("${PROJECT_SOURCE_DIR}/lib/glew")
include_directories("${PROJECT_SOURCE_DIR}/lib/glew/include")
@@ -365,6 +366,11 @@ if(UNIX AND NOT APPLE)
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)
# 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 :

View File

@@ -1,6 +1,7 @@
# 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`
@@ -26,8 +27,10 @@ First, make sure that you have the following packages installed:
Ubuntu command:
```
sudo apt-get install autoconf automake build-essential cmake libogg-dev libvorbis-dev libopenal-dev libxxf86vm-dev \
libgl1-mesa-dev libglu1-mesa-dev libcurl4-openssl-dev libfribidi-dev libbluetooth-dev libxrandr-dev libfreetype6-dev
sudo apt-get install build-essential cmake libbluetooth-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:

Binary file not shown.

View File

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

View File

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

View File

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

View File

@@ -9,7 +9,9 @@
<spacer height="25" width="10"/>
<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_achievements" width="128" height="128" icon="gui/gp_copy.png"
I18N="Section in the profile screen" text="Achievements"/>
<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"/>
<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_friends" width="128" height="128" icon="gui/options_players.png"
I18N="Section in the profile screen" text="Friends"/>

View File

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

View File

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

View File

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

View File

@@ -46,6 +46,7 @@ void CentralVideoSettings::init()
hasMultiDrawIndirect = false;
hasTextureCompression = false;
hasUBO = false;
hasExplicitAttribLocation = false;
hasGS = false;
m_GI_has_artifact = false;
@@ -154,11 +155,24 @@ void CentralVideoSettings::init()
hasUBO = true;
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")) {
hasGS = true;
Log::info("GLDriver", "ARB Geometry Shader 4 Present");
}
#endif
// 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.
@@ -229,7 +243,7 @@ bool CentralVideoSettings::needsSRGBCapableVisualWorkaround() const
return m_need_srgb_visual_workaround;
}
bool CentralVideoSettings::isARBGeometryShader4Usable() const
bool CentralVideoSettings::isARBGeometryShadersUsable() const
{
return hasGS;
}
@@ -239,6 +253,11 @@ bool CentralVideoSettings::isARBUniformBufferObjectUsable() const
return hasUBO;
}
bool CentralVideoSettings::isARBExplicitAttribLocationUsable() const
{
return hasExplicitAttribLocation;
}
bool CentralVideoSettings::isEXTTextureCompressionS3TCUsable() const
{
return hasTextureCompression;
@@ -311,12 +330,12 @@ bool CentralVideoSettings::isARBMultiDrawIndirectUsable() const
bool CentralVideoSettings::supportsShadows() const
{
return isARBGeometryShader4Usable() && isARBUniformBufferObjectUsable();
return isARBGeometryShadersUsable() && isARBUniformBufferObjectUsable() && isARBExplicitAttribLocationUsable();
}
bool CentralVideoSettings::supportsGlobalIllumination() const
{
return isARBGeometryShader4Usable() && isARBUniformBufferObjectUsable() && !m_GI_has_artifact;
return isARBGeometryShadersUsable() && isARBUniformBufferObjectUsable() && isARBExplicitAttribLocationUsable() && !m_GI_has_artifact;
}
bool CentralVideoSettings::supportsIndirectInstancingRendering() const

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -419,8 +419,7 @@ void initTexturesTransparent(GLMesh &mesh)
{
if (!mesh.textures[0])
{
Log::fatal("STKMesh", "Missing texture for material transparent");
return;
mesh.textures[0] = getUnicolorTexture(video::SColor(255, 255, 255, 255));
}
compressTexture(mesh.textures[0], true);
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++)
{
if (!found) continue;
Vec3 d = BattleGraph::get()
->getPolyOfNode(used_location[j]).getCenter() -
BattleGraph::get()->getPolyOfNode(node).getCenter();
found = d.length_2d() > MIN_DIST;
float test_distance = BattleGraph::get()
->getDistance(used_location[j], node);
found = test_distance > MIN_DIST;
}
if (found)
{

View File

@@ -283,23 +283,24 @@ void AIBaseController::crashed(const Material *m)
} // crashed(Material)
//-----------------------------------------------------------------------------
void AIBaseController::checkPosition(const Vec3 &point,
posData *pos_data,
Vec3 *lc) const
void AIBaseController::checkPosition(const Vec3 &point, posData *pos_data,
Vec3 *lc, bool use_front_xyz) const
{
// Convert to local coordinates from the point of view of current kart
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);
// Save local coordinates for later use if needed
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)
pos_data->on_side = true;
pos_data->lhs = true;
else
pos_data->on_side = false;
pos_data->lhs = false;
// behind: tell whether it's behind or not
if (local_coordinates.getZ() < 0)
@@ -309,6 +310,6 @@ void AIBaseController::checkPosition(const Vec3 &point,
pos_data->angle = atan2(fabsf(local_coordinates.getX()),
fabsf(local_coordinates.getZ()));
pos_data->distance = p.length_2d();
pos_data->distance = p.length();
} // checkPosition

View File

@@ -65,7 +65,7 @@ protected:
static int m_test_ai;
/** 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);
float steerToPoint(const Vec3 &point);
@@ -77,7 +77,9 @@ protected:
/** This can be called to detect if the kart is stuck (i.e. repeatedly
* hitting part of the track). */
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:
AIBaseController(AbstractKart *kart);

View File

@@ -29,10 +29,20 @@
#include "tracks/battle_graph.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)
: AIBaseController(kart)
{
m_debug_sphere = NULL;
m_debug_sphere_next = NULL;
} // ArenaAI
//-----------------------------------------------------------------------------
@@ -41,6 +51,8 @@ ArenaAI::ArenaAI(AbstractKart *kart)
void ArenaAI::reset()
{
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_closest_kart = NULL;
m_closest_kart_node = BattleGraph::UNKNOWN_POLY;
@@ -49,14 +61,17 @@ void ArenaAI::reset()
m_cur_kart_pos_data = {0};
m_is_stuck = false;
m_is_uturn = false;
m_avoiding_banana = false;
m_target_point = Vec3(0, 0, 0);
m_time_since_last_shot = 0.0f;
m_time_since_driving = 0.0f;
m_time_since_reversing = 0.0f;
m_time_since_uturn = 0.0f;
m_turn_radius = 0.0f;
m_turn_angle = 0.0f;
m_on_node.clear();
m_path_corners.clear();
m_portals.clear();
m_aiming_points.clear();
m_aiming_nodes.clear();
m_cur_difficulty = race_manager->getDifficulty();
AIBaseController::reset();
@@ -72,10 +87,14 @@ void ArenaAI::update(float dt)
// This is used to enable firing an item backwards.
m_controls->m_look_back = false;
m_controls->m_nitro = false;
m_avoiding_banana = false;
// Don't do anything if there is currently a kart animations shown.
if (m_kart->getKartAnimation())
{
resetAfterStop();
return;
}
if (isWaiting())
{
@@ -90,16 +109,16 @@ void ArenaAI::update(float dt)
findClosestKart(true);
findTarget();
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;
}
if (m_is_uturn)
{
resetAfterStop();
handleArenaUTurn(dt);
}
else
@@ -113,6 +132,129 @@ void ArenaAI::update(float dt)
} // 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)
{
@@ -154,6 +296,7 @@ void ArenaAI::checkIfStuck(const float dt)
*/
void ArenaAI::handleArenaAcceleration(const float dt)
{
if (m_controls->m_brake)
{
m_controls->m_accel = 0.0f;
@@ -173,7 +316,7 @@ void ArenaAI::handleArenaUTurn(const float dt)
if (fabsf(m_kart->getSpeed()) >
(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;
else
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;
resetAfterStop();
setSteering(0.0f, dt);
if (fabsf(m_kart->getSpeed()) >
@@ -223,287 +367,76 @@ bool ArenaAI::handleArenaUnstuck(const float dt)
} // handleArenaUnstuck
//-----------------------------------------------------------------------------
/** This function sets the steering.
* \param dt Time step size.
*/
void ArenaAI::handleArenaSteering(const float dt)
void ArenaAI::updateBananaLocation()
{
const int current_node = getCurrentNode();
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 =
std::vector<std::pair<const Item*, int>>& item_list =
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;
if (item->getType() == Item::ITEM_BANANA && !item->wasCollected())
m_test_node_for_banana = *node;
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(0, 0, 0);
checkPosition(item->getXYZ(), &banana_pos, &banana_lc);
if (banana_pos.angle < 0.2f && banana_pos.distance < 7.5f &&
!banana_pos.behind)
Vec3 banana_lc;
checkPosition(it->first->getXYZ(), NULL, &banana_lc,
true/*use_front_xyz*/);
// 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
// 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;
node++;
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;
}
//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;
}
}
node++;
}
//Push end_pos to m_path_corners so if no corners, we aim at target
m_path_corners.push_back(end_pos);
} // stringPull
} // updateBananaLocation
//-----------------------------------------------------------------------------
/** This function handles braking. It calls determineTurnRadius() to find out
* the curve radius. Depending on the turn radius, it finds out the maximum
/** This function handles braking. It used the turn radius found by
* 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, brakes are applied.
*/
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
// value. This prevents a kart from going too slow (or even backwards)
// in tight curves.
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());
points.push_back(m_path_corners[0]);
points.push_back((m_path_corners.size()>=2) ? m_path_corners[1] : m_path_corners[0]);
m_controls->m_brake = false;
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;
Vec3 d2 = m_kart->getXYZ() - m_path_corners[0];
if (d1.length2_2d() < d2.length2_2d())
current_curve_radius = d1.length_2d();
if (m_aiming_points.empty()) return;
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_controls->m_brake = true;
@@ -512,60 +445,58 @@ void ArenaAI::handleArenaBraking()
} // handleArenaBraking
//-----------------------------------------------------------------------------
/** The turn radius is determined by fitting a parabola to 3 points: current
* location of AI, first corner and the second corner. Once the constants are
* 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 )
void ArenaAI::updateTurnRadius(const Vec3& p1, const Vec3& p2,
const Vec3& p3)
{
// Declaring variables
float a, b;
irr::core::CMatrix4<float> A;
irr::core::CMatrix4<float> X;
irr::core::CMatrix4<float> B;
// First use cosine formula to find out the angle made by the distance
// between kart (point one) to point two and point two between point three
const float a = (p1 - p2).length();
const float b = (p2 - p3).length();
const float c = (p1 - p3).length();
const float angle = 180 - findAngleFrom3Edges(a, b, c);
//Populating matrices
for (unsigned int i = 0; i < 3; i++)
// Only calculate radius if not almost straight line
if (angle > 1 && angle < 179)
{
A(i, 0) = points[i].x()*points[i].x();
A(i, 1) = points[i].x();
A(i, 2) = 1.0f;
A(i, 3) = 0.0f;
// angle
// ^
// a / \ b
// 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;
A(3, 3) = 1.0f;
for (unsigned int i = 0; i < 3; i++)
else
{
B(i, 0) = points[i].z();
B(i, 1) = 0.0f;
B(i, 2) = 0.0f;
B(i, 3) = 0.0f;
// Return large radius so no braking is needed otherwise
m_turn_radius = 45.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
irr::core::CMatrix4<float> invA;
if (!A.getInverse(invA))
return -1;
} // updateTurnRadius
X = invA*B;
a = X(0, 0);
b = X(0, 1);
//c = X(0, 2);
//-----------------------------------------------------------------------------
float ArenaAI::findAngleFrom3Edges(float a, float b, float c)
{
// 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();
//float z = a*pow(x, 2) + b*x + c;
float dx_by_dz = 2*a*x + b;
float d2x_by_dz = 2*a;
return acosf(test_value) * RAD_TO_DEGREE;
float radius = pow(abs(1 + pow(dx_by_dz, 2)), 1.5f)/ abs(d2x_by_dz);
return radius;
} // determineTurnRadius
} // findAngleFrom3Edges
//-----------------------------------------------------------------------------
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_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_look_back = fire_behind;
@@ -755,14 +687,15 @@ void ArenaAI::collectItemInArena(Vec3* aim_point, int* target_node) const
m_kart->getKartProperties()->getNitroSmallContainer()))
continue; // Ignore nitro when already has some
Vec3 d = item->getXYZ() - m_kart->getXYZ();
if (d.length_2d() <= distance &&
float test_distance = BattleGraph::get()
->getDistance(item_list[i].second, getCurrentNode());
if (test_distance <= distance &&
(item->getType() == Item::ITEM_BONUS_BOX ||
item->getType() == Item::ITEM_NITRO_BIG ||
item->getType() == Item::ITEM_NITRO_SMALL))
{
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
* is targeting at. */
irr::scene::ISceneNode *m_debug_sphere;
irr::scene::ISceneNode *m_debug_sphere_next;
/** The node(poly) at which the target point lies in. */
int m_target_node;
@@ -63,7 +64,10 @@ protected:
/** The 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:
/** Used by handleArenaUTurn, it tells whether to do left or right
* turning when steering is overridden. */
@@ -81,15 +85,7 @@ private:
/** Holds the unique node ai has driven through, useful to tell if AI is
* stuck by determine the size of this set. */
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;
std::set<int> m_on_node;
/** Time an item has been collected and not used. */
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. */
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);
float determineTurnRadius(std::vector<Vec3>& points);
void findPortals(int start, int end);
void handleArenaAcceleration(const float dt);
void handleArenaBanana();
void handleArenaBraking();
void handleArenaItems(const float dt);
void handleArenaSteering(const float dt);
void handleArenaUTurn(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 bool isWaiting() const = 0;
virtual void resetAfterStop() {};
virtual void findClosestKart(bool use_difficulty) = 0;
virtual void findTarget() = 0;
virtual bool forceBraking() { return m_avoiding_banana; }
virtual bool ignorePathFinding() { return false; }
public:
static int m_test_node_for_banana;
ArenaAI(AbstractKart *kart);
virtual ~ArenaAI() {};
virtual void update (float delta);

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