what done?

This commit is contained in:
=
2016-09-27 15:43:48 +02:00
parent 9d0401496f
commit 8218977825
1443 changed files with 93549 additions and 0 deletions

View File

@ -0,0 +1,28 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.julian.endlessroll">
<uses-feature
android:glEsVersion="0x00020000"
android:required="true" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true">
android:theme="@style/AppTheme">
<activity
android:name=".main.GameActivity"
android:configChanges="orientation|screenSize|keyboardHidden"
android:screenOrientation="landscape">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>

Binary file not shown.

View File

@ -0,0 +1,44 @@
<?xml version="1.0" encoding="utf-8"?>
<levelPack name="Levelpack 1">
<levels>
<level goalX="24" number="1">
<terrain endX="27" height="-0.6">
<gaps>
<gap leftEdge="4" rightEdge="5"/>
<gap leftEdge="12" rightEdge="13"/>
<gap leftEdge="16" rightEdge="16.5"/>
<gap leftEdge="16.8" rightEdge="17.3"/>
</gaps>
</terrain>
<obstacles>
<obstacle height="0.3" leftEdge="9" rightEdge="10" type="default"/>
<obstacle height="0.2" leftEdge="13" rightEdge="14" type="default"/>
<obstacle height="0.3" leftEdge="18" rightEdge="20" type="default"/>
<obstacle height="0.5" leftEdge="20" rightEdge="21" type="default"/>
<obstacle height="0.1" leftEdge="21" rightEdge="22" type="default"/>
</obstacles>
</level>
<level goalX="21.25" number="2">
<terrain endX="21" height="-0.6">
<gaps>
<gap leftEdge="1" rightEdge="1.7" />
<gap leftEdge="8.9" rightEdge="9.6" />
<gap leftEdge="9.7" rightEdge="10.4" />
<gap leftEdge="15" rightEdge="16.1" />
</gaps>
</terrain>
<obstacles>
<obstacle height="0.3" leftEdge="1.73" rightEdge="2.3" type="default" />
<obstacle height="0.5" leftEdge="2.9" rightEdge="3.6" type="default" />
<obstacle height="0.3" leftEdge="5" rightEdge="7" type="default" />
<obstacle height="0.52" leftEdge="7.1" rightEdge="8.5" type="default" />
<obstacle height="0.5" leftEdge="11.4" rightEdge="12.8" type="default" />
<obstacle height="0.5" leftEdge="13.9" rightEdge="14.2" type="default" />
<obstacle height="0.24" leftEdge="16.8" rightEdge="18.3" type="default" />
<obstacle height="0.35" leftEdge="18.30001" rightEdge="18.8" type="default" />
<obstacle height="0.54" leftEdge="18.80001" rightEdge="19.4" type="default" />
<obstacle height="0.41" leftEdge="19.40001" rightEdge="20.5" type="default" />
</obstacles>
</level>
</levels>
</levelPack>

View File

@ -0,0 +1,196 @@
<levelPack name="Grasslands" id="1">
<levels class="java.util.ArrayList">
<level number="1" goalX="22.606565">
<terrain height="-0.6" endX="25.106565">
<gaps class="java.util.ArrayList">
<gap leftEdge="5.3500023" rightEdge="5.950004"/>
<gap leftEdge="15.353701" rightEdge="15.7197"/>
</gaps>
</terrain>
<obstacles class="java.util.ArrayList">
<obstacleData type="" leftEdge="10.873024" rightEdge="11.427025" height="0.304" y="-0.448" attachedToGround="true"/>
<obstacleData type="" leftEdge="14.860029" rightEdge="15.360029" height="0.3" y="-0.45000002" attachedToGround="true"/>
<obstacleData type="" leftEdge="20.096622" rightEdge="22.096622" height="0.25" y="-0.47500002" attachedToGround="true"/>
<obstacleData type="" leftEdge="22.166656" rightEdge="22.666656" height="0.639" y="-0.28050002" attachedToGround="true"/>
</obstacles>
<stars class="java.util.ArrayList">
<starData index="1" x="11.159975" y="-0.15999995" width="0.25" height="0.25"/>
<starData index="2" x="15.106676" y="-0.14000002" width="0.25" height="0.25"/>
<starData index="3" x="22.043303" y="-0.20666662" width="0.25" height="0.25"/>
</stars>
</level>
<level number="2" goalX="22.366613">
<terrain height="-0.6" endX="25.36662">
<gaps class="java.util.ArrayList">
<gap leftEdge="4.863002" rightEdge="5.6970024"/>
<gap leftEdge="10.581718" rightEdge="11.33174"/>
<gap leftEdge="15.4032545" rightEdge="16.05025"/>
<gap leftEdge="19.54848" rightEdge="20.111479"/>
<gap leftEdge="20.609486" rightEdge="21.050488"/>
</gaps>
</terrain>
<obstacles class="java.util.ArrayList">
<obstacleData type="" leftEdge="3.3708305" rightEdge="4.8758307" height="0.2" y="-0.5" attachedToGround="true"/>
<obstacleData type="" leftEdge="11.334382" rightEdge="11.912381" height="0.319" y="-0.44050002" attachedToGround="true"/>
<obstacleData type="" leftEdge="2.4509985" rightEdge="3.3089983" height="0.275" y="-0.46250004" attachedToGround="true"/>
<obstacleData type="" leftEdge="1.6111658" rightEdge="2.3221657" height="0.338" y="-0.43100002" attachedToGround="true"/>
<obstacleData type="" leftEdge="16.037212" rightEdge="16.856213" height="0.435" y="-0.38250002" attachedToGround="true"/>
<obstacleData type="" leftEdge="16.873312" rightEdge="17.873312" height="0.367" y="-0.41650003" attachedToGround="true"/>
<obstacleData type="" leftEdge="17.884027" rightEdge="18.896029" height="0.327" y="-0.4365" attachedToGround="true"/>
<obstacleData type="" leftEdge="19.046677" rightEdge="19.546677" height="0.884" y="-0.15800002" attachedToGround="true"/>
<obstacleData type="" leftEdge="20.113306" rightEdge="20.613306" height="0.5" y="-0.35000002" attachedToGround="true"/>
</obstacles>
<stars class="java.util.ArrayList">
<starData index="1" x="10.94335" y="-0.61999965" width="0.25" height="0.25"/>
<starData index="2" x="15.7367" y="0.3199999" width="0.25" height="0.25"/>
<starData index="3" x="18.893328" y="-0.12666662" width="0.25" height="0.25"/>
</stars>
</level>
<level number="3" goalX="19.200012">
<terrain height="-0.6" endX="18.900013">
<gaps class="java.util.ArrayList">
<gap leftEdge="2.3799982" rightEdge="2.9799984"/>
<gap leftEdge="4.825835" rightEdge="5.200835"/>
<gap leftEdge="7.5069995" rightEdge="8.013"/>
</gaps>
</terrain>
<obstacles class="java.util.ArrayList">
<obstacleData type="" leftEdge="8.00651" rightEdge="8.67351" height="0.319" y="-0.44050002" attachedToGround="true"/>
<obstacleData type="" leftEdge="11.703371" rightEdge="12.7233715" height="0.299" y="-0.4505" attachedToGround="true"/>
<obstacleData type="" leftEdge="15.164396" rightEdge="15.762396" height="0.466" y="-0.36700004" attachedToGround="true"/>
<obstacleData type="" leftEdge="15.891703" rightEdge="16.901701" height="0.402" y="-0.39900002" attachedToGround="true"/>
<obstacleData type="" leftEdge="16.998373" rightEdge="18.248373" height="0.353" y="-0.42350003" attachedToGround="true"/>
<obstacleData type="" leftEdge="18.396694" rightEdge="18.896694" height="0.789" y="-0.20550004" attachedToGround="true"/>
</obstacles>
<stars class="java.util.ArrayList">
<starData index="1" x="2.6399994" y="0.10666669" width="0.25" height="0.25"/>
<starData index="2" x="8.793346" y="-0.4733331" width="0.25" height="0.25"/>
<starData index="3" x="12.253348" y="-0.13333318" width="0.25" height="0.25"/>
</stars>
</level>
<level number="4" goalX="23.639889">
<terrain height="-0.6" endX="23.639889">
<gaps class="java.util.ArrayList">
<gap leftEdge="15.903543" rightEdge="17.656546"/>
<gap leftEdge="20.776228" rightEdge="22.557226"/>
</gaps>
</terrain>
<obstacles class="java.util.ArrayList">
<obstacleData type="" leftEdge="1.948999" rightEdge="2.5509992" height="0.354" y="-0.42300004" attachedToGround="true"/>
<obstacleData type="" leftEdge="5.592169" rightEdge="8.321169" height="0.408" y="-0.39600003" attachedToGround="true"/>
<obstacleData type="" leftEdge="8.408872" rightEdge="11.137872" height="0.803" y="-0.19850004" attachedToGround="true"/>
<obstacleData type="" leftEdge="11.196732" rightEdge="14.196732" height="0.5" y="0.3966666" attachedToGround="false"/>
<obstacleData type="" leftEdge="14.865067" rightEdge="17.775066" height="0.299" y="0.48666632" attachedToGround="false"/>
<obstacleData type="" leftEdge="17.871216" rightEdge="18.522217" height="1.415" y="0.10749996" attachedToGround="true"/>
<obstacleData type="" leftEdge="18.612877" rightEdge="20.853878" height="0.231" y="0.55999976" attachedToGround="false"/>
</obstacles>
<stars class="java.util.ArrayList">
<starData index="1" x="11.560022" y="-0.26000002" width="0.25" height="0.25"/>
<starData index="2" x="16.310017" y="0.80666655" width="0.25" height="0.25"/>
<starData index="3" x="21.629972" y="-0.12" width="0.25" height="0.25"/>
</stars>
</level>
<level number="5" goalX="16.249996">
<terrain height="-0.6" endX="18.249996">
<gaps class="java.util.ArrayList">
<gap leftEdge="6.810508" rightEdge="8.329505"/>
</gaps>
</terrain>
<obstacles class="java.util.ArrayList">
<obstacleData type="" leftEdge="2.3669987" rightEdge="2.7929988" height="1.074" y="-0.06300002" attachedToGround="true"/>
<obstacleData type="" leftEdge="12.000204" rightEdge="13.373203" height="0.946" y="-0.12700003" attachedToGround="true"/>
<obstacleData type="" leftEdge="13.539708" rightEdge="15.093709" height="0.725" y="-0.23750001" attachedToGround="true"/>
<obstacleData type="" leftEdge="15.29672" rightEdge="15.79672" height="1.539" y="0.1695" attachedToGround="true"/>
</obstacles>
<stars class="java.util.ArrayList">
<starData index="1" x="2.5799987" y="0.62" width="0.25" height="0.25"/>
<starData index="2" x="7.5566673" y="0.26000008" width="0.25" height="0.25"/>
<starData index="3" x="11.85002" y="-0.4533334" width="0.25" height="0.25"/>
</stars>
</level>
<level number="6" goalX="27.539873">
<terrain height="-0.6" endX="26.939873">
<gaps class="java.util.ArrayList">
<gap leftEdge="4.026832" rightEdge="5.179832"/>
<gap leftEdge="9.292203" rightEdge="10.061208"/>
<gap leftEdge="10.566699" rightEdge="11.166699"/>
<gap leftEdge="16.414387" rightEdge="16.75238"/>
</gaps>
</terrain>
<obstacles class="java.util.ArrayList">
<obstacleData type="" leftEdge="1.1131666" rightEdge="1.5001667" height="0.941" y="-0.12950003" attachedToGround="true"/>
<obstacleData type="" leftEdge="1.6498328" rightEdge="1.7768329" height="0.902" y="-0.14900002" attachedToGround="true"/>
<obstacleData type="" leftEdge="1.9103338" rightEdge="2.1163337" height="0.838" y="-0.18100002" attachedToGround="true"/>
<obstacleData type="" leftEdge="2.224499" rightEdge="2.415499" height="0.735" y="-0.23250002" attachedToGround="true"/>
<obstacleData type="" leftEdge="2.500666" rightEdge="2.6726658" height="0.613" y="-0.29350004" attachedToGround="true"/>
<obstacleData type="" leftEdge="2.731666" rightEdge="3.961666" height="0.5" y="-0.35000002" attachedToGround="true"/>
<obstacleData type="" leftEdge="5.1713314" rightEdge="5.955332" height="0.186" y="-0.507" attachedToGround="true"/>
<obstacleData type="" leftEdge="10.060041" rightEdge="10.560041" height="0.843" y="-0.17850003" attachedToGround="true"/>
<obstacleData type="" leftEdge="20.506636" rightEdge="20.806635" height="0.558" y="-0.321" attachedToGround="true"/>
<obstacleData type="" leftEdge="20.5105" rightEdge="20.8095" height="0.286" y="0.9333331" attachedToGround="false"/>
<obstacleData type="" leftEdge="14.943075" rightEdge="16.437075" height="0.231" y="-0.48450002" attachedToGround="true"/>
<obstacleData type="" leftEdge="25.285612" rightEdge="26.707613" height="0.599" y="-0.30050004" attachedToGround="true"/>
</obstacles>
<stars class="java.util.ArrayList">
<starData index="1" x="4.586666" y="-0.5866665" width="0.25" height="0.25"/>
<starData index="2" x="10.696706" y="-0.46666694" width="0.25" height="0.25"/>
<starData index="3" x="20.64665" y="0.39999995" width="0.25" height="0.25"/>
</stars>
</level>
<level number="7" goalX="25.473257">
<terrain height="-0.6" endX="28.473238">
<gaps class="java.util.ArrayList">
<gap leftEdge="7.3475013" rightEdge="9.372511"/>
<gap leftEdge="9.8666935" rightEdge="10.466708"/>
<gap leftEdge="15.304541" rightEdge="16.335531"/>
<gap leftEdge="19.761318" rightEdge="20.305317"/>
<gap leftEdge="24.703619" rightEdge="25.36962"/>
</gaps>
</terrain>
<obstacles class="java.util.ArrayList">
<obstacleData type="" leftEdge="2.9593315" rightEdge="3.9473314" height="0.313" y="-0.01333334" attachedToGround="false"/>
<obstacleData type="" leftEdge="3.987667" rightEdge="5.565667" height="0.272" y="-0.046666723" attachedToGround="false"/>
<obstacleData type="" leftEdge="8.7657" rightEdge="10.8077" height="0.095" y="-0.5525" attachedToGround="true"/>
<obstacleData type="" leftEdge="5.595845" rightEdge="6.950845" height="0.19" y="-0.073333286" attachedToGround="false"/>
<obstacleData type="" leftEdge="15.055702" rightEdge="16.537703" height="0.218" y="-0.49100003" attachedToGround="true"/>
<obstacleData type="" leftEdge="6.992841" rightEdge="7.353841" height="0.558" y="-0.321" attachedToGround="true"/>
<obstacleData type="" leftEdge="19.35432" rightEdge="19.75232" height="0.762" y="-0.21900001" attachedToGround="true"/>
<obstacleData type="" leftEdge="19.963318" rightEdge="20.463318" height="0.5" y="0.7533332" attachedToGround="false"/>
<obstacleData type="" leftEdge="20.287636" rightEdge="21.245636" height="0.435" y="-0.38250002" attachedToGround="true"/>
<obstacleData type="" leftEdge="20.503141" rightEdge="21.190142" height="0.5" y="0.42999995" attachedToGround="false"/>
</obstacles>
<stars class="java.util.ArrayList">
<starData index="1" x="6.6800065" y="-0.38666666" width="0.25" height="0.25"/>
<starData index="2" x="15.820039" y="-0.7866664" width="0.25" height="0.25"/>
<starData index="3" x="20.679989" y="0.85333335" width="0.25" height="0.25"/>
</stars>
</level>
<level number="8" goalX="20.523335">
<terrain height="-0.6" endX="23.523335">
<gaps class="java.util.ArrayList">
<gap leftEdge="-1.3473341" rightEdge="2.240666"/>
<gap leftEdge="3.05333" rightEdge="7.05333"/>
<gap leftEdge="11.257536" rightEdge="14.282536"/>
<gap leftEdge="15.696874" rightEdge="16.10987"/>
</gaps>
</terrain>
<obstacles class="java.util.ArrayList">
<obstacleData type="" leftEdge="-0.9233334" rightEdge="2.0766666" height="0.136" y="-0.90666574" attachedToGround="false"/>
<obstacleData type="" leftEdge="4.979664" rightEdge="5.9736643" height="0.286" y="-0.89333284" attachedToGround="false"/>
<obstacleData type="" leftEdge="3.057998" rightEdge="3.9619977" height="0.299" y="-0.81333286" attachedToGround="false"/>
<obstacleData type="" leftEdge="3.9729972" rightEdge="4.9669976" height="0.286" y="-0.8533326" attachedToGround="false"/>
<obstacleData type="" leftEdge="5.997839" rightEdge="6.8288393" height="0.231" y="-0.9199996" attachedToGround="false"/>
<obstacleData type="" leftEdge="11.854198" rightEdge="13.119198" height="1.02" y="0.023333304" attachedToGround="false"/>
<obstacleData type="" leftEdge="13.141195" rightEdge="13.792196" height="0.639" y="0.18666656" attachedToGround="false"/>
<obstacleData type="" leftEdge="14.541548" rightEdge="15.698547" height="0.422" y="-0.38900003" attachedToGround="true"/>
<obstacleData type="" leftEdge="20.074863" rightEdge="20.851864" height="1.02" y="-0.09000003" attachedToGround="true"/>
<obstacleData type="" leftEdge="11.280017" rightEdge="14.280017" height="0.218" y="-1.1066662" attachedToGround="false"/>
</obstacles>
<stars class="java.util.ArrayList">
<starData index="1" x="2.6366663" y="0.44666678" width="0.25" height="0.25"/>
<starData index="2" x="14.12338" y="-0.79999965" width="0.25" height="0.25"/>
<starData index="3" x="20.230003" y="0.5599996" width="0.25" height="0.25"/>
</stars>
</level>
</levels>
</levelPack>

View File

@ -0,0 +1,50 @@
<levelPack name="Testcave" id="0" terrainHeight="0.306" ceilingHeight="0.538">
<levels class="java.util.ArrayList">
<level number="1" goalX="32.129963" startSpeed="0.25" endSpeed="0.7">
<terrainTiles class="entities.tileLists.Terrain">
<tile x="-1.6499999" width="2.7000003"/>
<tile x="0.6273333" width="0.6546662"/>
<tile x="5.837672" width="5.558014"/>
</terrainTiles>
<ceilingTiles class="entities.tileLists.Ceiling">
<tile x="-0.41333365" width="5.1733327"/>
<tile x="7.895005" width="1.4433479"/>
</ceilingTiles>
<obstacles class="java.util.ArrayList">
<obstacleData type="" leftEdge="9.0" rightEdge="10.0" height="0.3" y="-0.45000002" attachedToGround="true"/>
<obstacleData type="" leftEdge="13.0" rightEdge="14.0" height="0.2" y="-0.5" attachedToGround="true"/>
<obstacleData type="" leftEdge="19.52634" rightEdge="20.580341" height="0.3" y="-0.45000002" attachedToGround="true"/>
<obstacleData type="" leftEdge="20.580004" rightEdge="21.580004" height="0.5" y="-0.35000002" attachedToGround="true"/>
<obstacleData type="" leftEdge="21.580002" rightEdge="22.580002" height="0.1" y="-0.55" attachedToGround="true"/>
<obstacleData type="" leftEdge="1.6033329" rightEdge="2.103333" height="0.5" y="-0.18399999" attachedToGround="true"/>
<obstacleData type="default" leftEdge="-0.25" rightEdge="0.25" height="0.5" y="0.0" attachedToGround="false"/>
<obstacleData type="default" leftEdge="-0.25" rightEdge="0.25" height="0.5" y="0.0" attachedToGround="false"/>
<obstacleData type="default" leftEdge="-0.25" rightEdge="0.25" height="0.5" y="0.0" attachedToGround="true"/>
<obstacleData type="default" leftEdge="-0.25" rightEdge="0.25" height="0.5" y="0.0" attachedToGround="false"/>
<obstacleData type="default" leftEdge="-0.25" rightEdge="0.25" height="0.5" y="0.0" attachedToGround="false"/>
</obstacles>
<stars class="java.util.ArrayList">
<starData index="1" x="10.163283" y="-0.05999978" width="0.25" height="0.25"/>
<starData index="2" x="19.366709" y="-0.046666652" width="0.25" height="0.25"/>
<starData index="3" x="21.73662" y="0.05333341" width="0.25" height="0.25"/>
</stars>
</level>
<level number="3" goalX="8.616679" startSpeed="0.19" endSpeed="0.44">
<terrainTiles class="entities.tileLists.Terrain">
<tile x="-1.0226668" width="3.9546664"/>
<tile x="5.837672" width="5.5580134"/>
</terrainTiles>
<ceilingTiles class="entities.tileLists.Ceiling">
<tile x="-0.43666697" width="5.126666"/>
<tile x="7.8716717" width="1.4900146"/>
</ceilingTiles>
<obstacles class="java.util.ArrayList">
<obstacleData type="" leftEdge="1.3278332" rightEdge="3.098833" height="0.5" y="-0.2733331" attachedToGround="false"/>
<obstacleData type="" leftEdge="4.0364995" rightEdge="6.2235" height="0.109" y="0.61333334" attachedToGround="false"/>
</obstacles>
<stars class="java.util.ArrayList">
<starData index="1" x="6.0466657" y="0.83333325" width="0.25" height="0.25"/>
</stars>
</level>
</levels>
</levelPack>

View File

@ -0,0 +1,106 @@
<levelPack name="First Pack">
<levels class="java.util.ArrayList">
<level number="1" goalX="22.259893">
<terrain height="-0.6" endX="23.259893">
<gaps class="java.util.ArrayList">
<gap leftEdge="5.3500023" rightEdge="5.950004"/>
<gap leftEdge="15.353701" rightEdge="15.7197"/>
</gaps>
</terrain>
<obstacles class="java.util.ArrayList">
<obstacleData type="" leftEdge="10.873024" rightEdge="11.427025" height="0.304" y="-0.448" attachedToGround="true"/>
<obstacleData type="" leftEdge="14.860029" rightEdge="15.360029" height="0.3" y="-0.45000002" attachedToGround="true"/>
<obstacleData type="" leftEdge="19.383318" rightEdge="21.383318" height="0.25" y="-0.47500002" attachedToGround="true"/>
<obstacleData type="" leftEdge="21.586645" rightEdge="22.086645" height="0.5" y="-0.35000002" attachedToGround="true"/>
</obstacles>
<stars class="java.util.ArrayList">
<starData x="11.150023" y="-0.1200001" width="0.25" height="0.25"/>
<starData x="15.120053" y="-0.12666668" width="0.25" height="0.25"/>
<starData x="21.42998" y="-0.20666662" width="0.25" height="0.25"/>
</stars>
</level>
<level number="2" goalX="16.220043">
<terrain height="-0.6" endX="19.220049">
<gaps class="java.util.ArrayList">
<gap leftEdge="4.8896685" rightEdge="5.723669"/>
<gap leftEdge="10.581718" rightEdge="11.33174"/>
<gap leftEdge="15.4032545" rightEdge="16.05025"/>
</gaps>
</terrain>
<obstacles class="java.util.ArrayList">
<obstacleData type="" leftEdge="3.3708305" rightEdge="4.8758307" height="0.2" y="-0.5" attachedToGround="true"/>
<obstacleData type="" leftEdge="11.334382" rightEdge="11.912381" height="0.319" y="-0.44050002" attachedToGround="true"/>
<obstacleData type="" leftEdge="2.4509985" rightEdge="3.3089983" height="0.275" y="-0.46250004" attachedToGround="true"/>
<obstacleData type="" leftEdge="1.6111658" rightEdge="2.3221657" height="0.338" y="-0.43100002" attachedToGround="true"/>
</obstacles>
<stars class="java.util.ArrayList">
<starData x="5.310005" y="-0.61333305" width="0.25" height="0.25"/>
<starData x="10.976699" y="-0.6333332" width="0.25" height="0.25"/>
<starData x="15.743367" y="0.31333324" width="0.25" height="0.25"/>
</stars>
</level>
<level number="3" goalX="19.146683">
<terrain height="-0.6" endX="18.846684">
<gaps class="java.util.ArrayList">
<gap leftEdge="2.3799982" rightEdge="2.9799984"/>
<gap leftEdge="4.825835" rightEdge="5.200835"/>
<gap leftEdge="7.5069995" rightEdge="8.013"/>
</gaps>
</terrain>
<obstacles class="java.util.ArrayList">
<obstacleData type="" leftEdge="8.00651" rightEdge="8.67351" height="0.319" y="-0.44050002" attachedToGround="true"/>
<obstacleData type="" leftEdge="11.703371" rightEdge="12.7233715" height="0.299" y="-0.4505" attachedToGround="true"/>
<obstacleData type="" leftEdge="15.164396" rightEdge="15.762396" height="0.466" y="-0.36700004" attachedToGround="true"/>
<obstacleData type="" leftEdge="15.818368" rightEdge="16.828367" height="0.402" y="-0.39900002" attachedToGround="true"/>
<obstacleData type="" leftEdge="16.858376" rightEdge="18.108376" height="0.353" y="-0.42350003" attachedToGround="true"/>
<obstacleData type="" leftEdge="18.216705" rightEdge="18.716705" height="0.789" y="-0.20550004" attachedToGround="true"/>
</obstacles>
<stars class="java.util.ArrayList">
<starData x="2.6933327" y="0.1266667" width="0.25" height="0.25"/>
<starData x="8.853351" y="-0.4533331" width="0.25" height="0.25"/>
<starData x="12.253348" y="-0.13333318" width="0.25" height="0.25"/>
</stars>
</level>
<level number="4" goalX="17.23667">
<terrain height="-0.6" endX="19.23667">
<gaps class="java.util.ArrayList">
<gap leftEdge="6.810508" rightEdge="8.329505"/>
</gaps>
</terrain>
<obstacles class="java.util.ArrayList">
<obstacleData type="" leftEdge="2.3669987" rightEdge="2.7929988" height="1.074" y="-0.06300002" attachedToGround="true"/>
<obstacleData type="" leftEdge="11.929536" rightEdge="13.150537" height="0.946" y="-0.12700003" attachedToGround="true"/>
<obstacleData type="" leftEdge="13.377707" rightEdge="14.495707" height="0.725" y="-0.23750001" attachedToGround="true"/>
<obstacleData type="" leftEdge="14.676702" rightEdge="15.176702" height="1.539" y="0.1695" attachedToGround="true"/>
</obstacles>
<stars class="java.util.ArrayList">
<starData x="2.573332" y="0.62" width="0.25" height="0.25"/>
<starData x="7.5566673" y="0.26000008" width="0.25" height="0.25"/>
<starData x="11.710016" y="-0.42666656" width="0.25" height="0.25"/>
</stars>
</level>
<level number="5" goalX="10.1833515">
<terrain height="-0.6" endX="9.483352">
<gaps class="java.util.ArrayList">
<gap leftEdge="4.026832" rightEdge="5.179832"/>
<gap leftEdge="8.085517" rightEdge="8.854522"/>
</gaps>
</terrain>
<obstacles class="java.util.ArrayList">
<obstacleData type="" leftEdge="1.1131666" rightEdge="1.5001667" height="0.941" y="-0.12950003" attachedToGround="true"/>
<obstacleData type="" leftEdge="1.6498328" rightEdge="1.7768329" height="0.902" y="-0.14900002" attachedToGround="true"/>
<obstacleData type="" leftEdge="1.9103338" rightEdge="2.1163337" height="0.838" y="-0.18100002" attachedToGround="true"/>
<obstacleData type="" leftEdge="2.224499" rightEdge="2.415499" height="0.735" y="-0.23250002" attachedToGround="true"/>
<obstacleData type="" leftEdge="2.500666" rightEdge="2.6726658" height="0.613" y="-0.29350004" attachedToGround="true"/>
<obstacleData type="" leftEdge="2.731666" rightEdge="3.961666" height="0.5" y="-0.35000002" attachedToGround="true"/>
<obstacleData type="" leftEdge="5.1713314" rightEdge="5.955332" height="0.186" y="-0.507" attachedToGround="true"/>
<obstacleData type="" leftEdge="8.860007" rightEdge="9.360007" height="0.843" y="-0.17850003" attachedToGround="true"/>
</obstacles>
<stars class="java.util.ArrayList">
<starData x="4.5599995" y="-0.54666656" width="0.25" height="0.25"/>
<starData x="6.203336" y="0.36666653" width="0.25" height="0.25"/>
<starData x="9.543362" y="-0.43333334" width="0.25" height="0.25"/>
</stars>
</level>
</levels>
</levelPack>

View File

@ -0,0 +1,84 @@
<levelPack name="Test Pack">
<levels class="java.util.ArrayList">
<level number="1" goalX="24.0">
<terrain height="-0.6" endX="27.0">
<gaps class="java.util.ArrayList">
<gap leftEdge="4.0" rightEdge="5.0"/>
<gap leftEdge="12.0" rightEdge="13.0"/>
<gap leftEdge="16.0" rightEdge="16.5"/>
<gap leftEdge="16.8" rightEdge="17.3"/>
</gaps>
</terrain>
<obstacles class="java.util.ArrayList">
<obstacleData type="" leftEdge="9.0" rightEdge="10.0" height="0.3" y="-0.45000002" attachedToGround="true"/>
<obstacleData type="" leftEdge="13.0" rightEdge="14.0" height="0.2" y="-0.5" attachedToGround="true"/>
<obstacleData type="" leftEdge="19.52634" rightEdge="20.580341" height="0.3" y="-0.45000002" attachedToGround="true"/>
<obstacleData type="" leftEdge="20.580004" rightEdge="21.580004" height="0.5" y="-0.35000002" attachedToGround="true"/>
<obstacleData type="" leftEdge="21.580002" rightEdge="22.580002" height="0.1" y="-0.55" attachedToGround="true"/>
</obstacles>
<stars class="java.util.ArrayList"/>
</level>
<level number="2" goalX="21.25">
<terrain height="-0.6" endX="21.0">
<gaps class="java.util.ArrayList">
<gap leftEdge="1.0" rightEdge="1.7"/>
<gap leftEdge="8.9" rightEdge="9.6"/>
<gap leftEdge="9.7" rightEdge="10.4"/>
<gap leftEdge="15.0" rightEdge="16.1"/>
</gaps>
</terrain>
<obstacles class="java.util.ArrayList">
<obstacleData type="" leftEdge="0.42333412" rightEdge="0.99333405" height="0.3" y="-0.45000002" attachedToGround="true"/>
<obstacleData type="" leftEdge="2.9" rightEdge="3.6" height="0.5" y="-0.35000002" attachedToGround="true"/>
<obstacleData type="" leftEdge="5.0" rightEdge="7.0" height="0.3" y="-0.45000002" attachedToGround="true"/>
<obstacleData type="" leftEdge="7.1000004" rightEdge="8.5" height="0.52" y="-0.34000003" attachedToGround="true"/>
<obstacleData type="" leftEdge="11.4" rightEdge="12.800001" height="0.5" y="-0.35000002" attachedToGround="true"/>
<obstacleData type="" leftEdge="13.9" rightEdge="14.199999" height="0.5" y="-0.35000002" attachedToGround="true"/>
<obstacleData type="" leftEdge="16.8" rightEdge="18.3" height="0.24" y="-0.48000002" attachedToGround="true"/>
<obstacleData type="" leftEdge="18.30001" rightEdge="18.8" height="0.35" y="-0.425" attachedToGround="true"/>
<obstacleData type="" leftEdge="18.80001" rightEdge="19.400002" height="0.54" y="-0.33" attachedToGround="true"/>
<obstacleData type="" leftEdge="19.40001" rightEdge="20.5" height="0.41" y="-0.39500004" attachedToGround="true"/>
</obstacles>
<stars class="java.util.ArrayList">
<starData x="0.19333333" y="-0.02" width="0.25" height="0.25"/>
</stars>
</level>
<level number="3" goalX="10.013344">
<terrain height="-0.6" endX="13.013344">
<gaps class="java.util.ArrayList">
<gap leftEdge="0.99333334" rightEdge="1.5933334"/>
<gap leftEdge="2.3266642" rightEdge="5.326664"/>
<gap leftEdge="5.376665" rightEdge="8.376666"/>
</gaps>
</terrain>
<obstacles class="java.util.ArrayList">
<obstacleData type="" leftEdge="1.0611664" rightEdge="1.5121664" height="0.431" y="-0.12666668" attachedToGround="false"/>
<obstacleData type="" leftEdge="2.615834" rightEdge="3.590834" height="0.181" y="-0.37333322" attachedToGround="false"/>
<obstacleData type="" leftEdge="3.5901666" rightEdge="4.2031665" height="0.27" y="-0.21999994" attachedToGround="false"/>
<obstacleData type="" leftEdge="4.1894994" rightEdge="4.910499" height="0.294" y="0.0" attachedToGround="false"/>
<obstacleData type="" leftEdge="5.1586647" rightEdge="6.5946646" height="0.279" y="-0.24049996" attachedToGround="false"/>
<obstacleData type="" leftEdge="5.76284" rightEdge="5.9838395" height="0.76" y="0.5999998" attachedToGround="false"/>
<obstacleData type="" leftEdge="6.808838" rightEdge="8.097838" height="0.211" y="-0.33999994" attachedToGround="false"/>
<obstacleData type="" leftEdge="8.2516775" rightEdge="8.761678" height="0.877" y="-0.16150004" attachedToGround="true"/>
</obstacles>
<stars class="java.util.ArrayList"/>
</level>
<level number="4" goalX="14.916662">
<terrain height="-0.6" endX="17.916662">
<gaps class="java.util.ArrayList">
<gap leftEdge="12.363373" rightEdge="12.963373"/>
</gaps>
</terrain>
<obstacles class="java.util.ArrayList">
<obstacleData type="" leftEdge="2.5548315" rightEdge="3.9518313" height="0.201" y="-0.09283342" attachedToGround="false"/>
<obstacleData type="" leftEdge="0.84966636" rightEdge="1.1636665" height="0.27" y="-0.46500003" attachedToGround="true"/>
<obstacleData type="" leftEdge="4.0266647" rightEdge="4.5266647" height="0.5" y="-0.35000002" attachedToGround="true"/>
<obstacleData type="" leftEdge="5.05683" rightEdge="6.16983" height="0.25" y="-0.09333334" attachedToGround="false"/>
<obstacleData type="" leftEdge="6.2320023" rightEdge="6.948002" height="0.5" y="-0.35000002" attachedToGround="true"/>
<obstacleData type="" leftEdge="7.572172" rightEdge="8.621172" height="0.284" y="-0.08666665" attachedToGround="false"/>
<obstacleData type="" leftEdge="8.682344" rightEdge="9.084345" height="1.142" y="0.40666664" attachedToGround="false"/>
</obstacles>
<stars class="java.util.ArrayList"/>
</level>
</levels>
</levelPack>

View File

@ -0,0 +1,12 @@
<levelPack name="test" id="1" terrainHeight="0.0" ceilingHeight="0.0">
<levels class="java.util.ArrayList">
<level number="2" goalX="3.0">
<terrainTiles class="java.util.ArrayList">
<tile x="0.0" width="6.0"/>
</terrainTiles>
<ceilingTiles class="java.util.ArrayList"/>
<obstacles class="java.util.ArrayList"/>
<stars class="java.util.ArrayList"/>
</level>
</levels>
</levelPack>

View File

@ -0,0 +1,157 @@
Untitled
- Delay -
active: false
- Duration -
lowMin: 300.0
lowMax: 300.0
- Count -
min: 0
max: 500
- Emission -
lowMin: 0.0
lowMax: 0.0
highMin: 60.0
highMax: 60.0
relative: false
scalingCount: 1
scaling0: 1.0
timelineCount: 1
timeline0: 0.0
- Life -
lowMin: 0.0
lowMax: 0.0
highMin: 600.0
highMax: 600.0
relative: false
scalingCount: 3
scaling0: 1.0
scaling1: 1.0
scaling2: 1.0
timelineCount: 3
timeline0: 0.0
timeline1: 0.66
timeline2: 1.0
- Life Offset -
active: false
- X Offset -
active: false
- Y Offset -
active: false
- Spawn Shape -
shape: point
- Spawn Width -
lowMin: 0.0
lowMax: 0.0
highMin: 0.0
highMax: 0.0
relative: false
scalingCount: 1
scaling0: 1.0
timelineCount: 1
timeline0: 0.0
- Spawn Height -
lowMin: 0.0
lowMax: 0.0
highMin: 0.0
highMax: 0.0
relative: false
scalingCount: 1
scaling0: 1.0
timelineCount: 1
timeline0: 0.0
- Scale -
lowMin: 15.0
lowMax: 15.0
highMin: 110.0
highMax: 110.0
relative: false
scalingCount: 3
scaling0: 0.0
scaling1: 0.19607843
scaling2: 0.60784316
timelineCount: 3
timeline0: 0.0
timeline1: 0.80136985
timeline2: 1.0
- Velocity -
active: true
lowMin: 1000.0
lowMax: 1000.0
highMin: -2000.0
highMax: -2000.0
relative: false
scalingCount: 3
scaling0: 0.0
scaling1: 0.0
scaling2: 1.0
timelineCount: 3
timeline0: 0.0
timeline1: 0.30170777
timeline2: 1.0
- Angle -
active: true
lowMin: 0.0
lowMax: 0.0
highMin: 0.0
highMax: 360.0
relative: false
scalingCount: 3
scaling0: 1.0
scaling1: 1.0
scaling2: 1.0
timelineCount: 3
timeline0: 0.0
timeline1: 0.7191781
timeline2: 1.0
- Rotation -
active: false
- Wind -
active: false
- Gravity -
active: false
- Tint -
colorsCount: 9
colors0: 1.0
colors1: 0.92941177
colors2: 0.047058824
colors3: 1.0
colors4: 0.92941177
colors5: 0.047058824
colors6: 1.0
colors7: 0.78039217
colors8: 0.047058824
timelineCount: 3
timeline0: 0.0
timeline1: 0.7521515
timeline2: 1.0
- Transparency -
lowMin: 0.0
lowMax: 0.0
highMin: 1.0
highMax: 1.0
relative: false
scalingCount: 7
scaling0: 0.0
scaling1: 1.0
scaling2: 1.0
scaling3: 1.0
scaling4: 1.0
scaling5: 1.0
scaling6: 0.0
timelineCount: 7
timeline0: 0.0
timeline1: 0.12068965
timeline2: 0.28767124
timeline3: 0.5
timeline4: 0.7873563
timeline5: 0.967433
timeline6: 1.0
- Options -
attached: false
continuous: false
aligned: false
additive: true
behind: false
premultipliedAlpha: false
- Image Path -
star.png

View File

@ -0,0 +1,184 @@
Untitled
- Delay -
active: false
- Duration -
lowMin: 500.0
lowMax: 500.0
- Count -
min: 0
max: 1000
- Emission -
lowMin: 0.0
lowMax: 0.0
highMin: 300.0
highMax: 300.0
relative: false
scalingCount: 4
scaling0: 1.0
scaling1: 0.74509805
scaling2: 0.3137255
scaling3: 0.0
timelineCount: 4
timeline0: 0.0
timeline1: 0.5205479
timeline2: 0.8630137
timeline3: 1.0
- Life -
lowMin: 0.0
lowMax: 0.0
highMin: 500.0
highMax: 800.0
relative: false
scalingCount: 3
scaling0: 1.0
scaling1: 1.0
scaling2: 0.3
timelineCount: 3
timeline0: 0.0
timeline1: 0.66
timeline2: 1.0
- Life Offset -
active: false
- X Offset -
active: false
- Y Offset -
active: false
- Spawn Shape -
shape: square
- Spawn Width -
lowMin: 200.0
lowMax: 200.0
highMin: 20.0
highMax: 20.0
relative: false
scalingCount: 2
scaling0: 0.0
scaling1: 0.0
timelineCount: 2
timeline0: 0.0
timeline1: 1.0
- Spawn Height -
lowMin: 200.0
lowMax: 200.0
highMin: 20.0
highMax: 20.0
relative: false
scalingCount: 2
scaling0: 0.0
scaling1: 0.0
timelineCount: 2
timeline0: 0.0
timeline1: 1.0
- Scale -
lowMin: 0.0
lowMax: 0.0
highMin: 27.0
highMax: 37.0
relative: false
scalingCount: 2
scaling0: 1.0
scaling1: 0.54901963
timelineCount: 2
timeline0: 0.0
timeline1: 1.0
- Velocity -
active: true
lowMin: 100.0
lowMax: 300.0
highMin: 500.0
highMax: 900.0
relative: false
scalingCount: 3
scaling0: 1.0
scaling1: 0.7647059
scaling2: 0.0
timelineCount: 3
timeline0: 0.0
timeline1: 0.69863015
timeline2: 1.0
- Angle -
active: true
lowMin: 90.0
lowMax: 90.0
highMin: 0.0
highMax: 360.0
relative: false
scalingCount: 3
scaling0: 1.0
scaling1: 1.0
scaling2: 1.0
timelineCount: 3
timeline0: 0.0
timeline1: 0.51369864
timeline2: 1.0
- Rotation -
active: false
- Wind -
active: true
lowMin: -50.0
lowMax: 50.0
highMin: -100.0
highMax: 100.0
relative: false
scalingCount: 2
scaling0: 0.0
scaling1: 1.0
timelineCount: 2
timeline0: 0.0
timeline1: 1.0
- Gravity -
active: false
- Tint -
colorsCount: 18
colors0: 0.07058824
colors1: 0.67058825
colors2: 1.0
colors3: 1.0
colors4: 0.7176471
colors5: 0.07058824
colors6: 1.0
colors7: 0.7411765
colors8: 0.07058824
colors9: 1.0
colors10: 0.12156863
colors11: 0.07058824
colors12: 0.9647059
colors13: 0.0
colors14: 0.0
colors15: 0.39607844
colors16: 0.047058824
colors17: 0.02745098
timelineCount: 6
timeline0: 0.0
timeline1: 0.024096385
timeline2: 0.09638554
timeline3: 0.59380376
timeline4: 0.9328744
timeline5: 1.0
- Transparency -
lowMin: 0.0
lowMax: 0.0
highMin: 1.0
highMax: 1.0
relative: false
scalingCount: 5
scaling0: 0.10526316
scaling1: 1.0
scaling2: 1.0
scaling3: 0.14035088
scaling4: 0.0
timelineCount: 5
timeline0: 0.0
timeline1: 0.2
timeline2: 0.5273973
timeline3: 0.74657536
timeline4: 1.0
- Options -
attached: false
continuous: false
aligned: false
additive: true
behind: false
premultipliedAlpha: false
- Image Path -
particle.png

View File

@ -0,0 +1,149 @@
Untitled
- Delay -
active: false
- Duration -
lowMin: 1000.0
lowMax: 1000.0
- Count -
min: 0
max: 500
- Emission -
lowMin: 0.0
lowMax: 0.0
highMin: 10.0
highMax: 10.0
relative: false
scalingCount: 1
scaling0: 1.0
timelineCount: 1
timeline0: 0.0
- Life -
lowMin: 0.0
lowMax: 0.0
highMin: 1300.0
highMax: 1600.0
relative: false
scalingCount: 3
scaling0: 1.0
scaling1: 1.0
scaling2: 1.0
timelineCount: 3
timeline0: 0.0
timeline1: 0.66
timeline2: 1.0
- Life Offset -
active: false
- X Offset -
active: false
- Y Offset -
active: false
- Spawn Shape -
shape: point
- Spawn Width -
lowMin: 0.0
lowMax: 0.0
highMin: 0.0
highMax: 0.0
relative: false
scalingCount: 1
scaling0: 1.0
timelineCount: 1
timeline0: 0.0
- Spawn Height -
lowMin: 0.0
lowMax: 0.0
highMin: 0.0
highMax: 0.0
relative: false
scalingCount: 1
scaling0: 1.0
timelineCount: 1
timeline0: 0.0
- Scale -
lowMin: 15.0
lowMax: 15.0
highMin: 30.0
highMax: 35.0
relative: false
scalingCount: 3
scaling0: 0.0
scaling1: 0.0
scaling2: 1.0
timelineCount: 3
timeline0: 0.0
timeline1: 0.37671232
timeline2: 1.0
- Velocity -
active: true
lowMin: 100.0
lowMax: 150.0
highMin: 370.0
highMax: 400.0
relative: false
scalingCount: 3
scaling0: 1.0
scaling1: 1.0
scaling2: 0.0
timelineCount: 3
timeline0: 0.0
timeline1: 0.08628652
timeline2: 0.087286524
- Angle -
active: true
lowMin: 0.0
lowMax: 0.0
highMin: 0.0
highMax: 360.0
relative: false
scalingCount: 3
scaling0: 1.0
scaling1: 1.0
scaling2: 1.0
timelineCount: 3
timeline0: 0.0
timeline1: 0.7191781
timeline2: 1.0
- Rotation -
active: false
- Wind -
active: false
- Gravity -
active: false
- Tint -
colorsCount: 6
colors0: 1.0
colors1: 1.0
colors2: 0.047058824
colors3: 1.0
colors4: 0.89411765
colors5: 0.047058824
timelineCount: 2
timeline0: 0.0
timeline1: 1.0
- Transparency -
lowMin: 0.0
lowMax: 0.0
highMin: 1.0
highMax: 1.0
relative: false
scalingCount: 5
scaling0: 0.0
scaling1: 0.0
scaling2: 1.0
scaling3: 1.0
scaling4: 0.0
timelineCount: 5
timeline0: 0.0
timeline1: 0.10344828
timeline2: 0.3659004
timeline3: 0.8082192
timeline4: 1.0
- Options -
attached: false
continuous: true
aligned: false
additive: true
behind: false
premultipliedAlpha: false
- Image Path -
particle.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

View File

@ -0,0 +1,29 @@
precision mediump float;
uniform sampler2D texture;
uniform float alpha;
uniform vec2 texAtlasSize;
uniform float texAtlasIndex;
varying vec2 pass_TexCoords;
vec2 getTexCoordsInAtlas(in float atlasIndex);
void main() {
vec2 texAtlasCoords = getTexCoordsInAtlas(texAtlasIndex);
gl_FragColor = texture2D(texture, texAtlasCoords);
gl_FragColor.a = min(gl_FragColor.a, alpha);
}
vec2 getTexCoordsInAtlas(in float atlasIndex){
vec2 texAtlasCoords = vec2(0.0, 0.0);
texAtlasCoords.x = mod(pass_TexCoords.x, 1.0) / texAtlasSize.x;
texAtlasCoords.x += mod(atlasIndex, texAtlasSize.x) / texAtlasSize.x;
texAtlasCoords.y = mod(pass_TexCoords.y, 1.0) / texAtlasSize.y;
texAtlasCoords.y += floor(atlasIndex / texAtlasSize.y) / texAtlasSize.y;
return texAtlasCoords;
}

View File

@ -0,0 +1,15 @@
uniform mat4 mvpMatrix;
uniform mat4 transformationMatrix;
attribute vec4 position;
attribute vec2 texCoords;
varying vec2 pass_TexCoords;
void main() {
vec4 transformatedPosition = transformationMatrix * position;
gl_Position = mvpMatrix * transformatedPosition;
pass_TexCoords = texCoords;
}

View File

@ -0,0 +1,13 @@
precision mediump float;
uniform sampler2D texture;
uniform vec3 color;
varying vec2 pass_TexCoords;
void main() {
gl_FragColor.a = texture2D(texture, pass_TexCoords).a;
gl_FragColor.rgb = color;
}

View File

@ -0,0 +1,11 @@
precision mediump float;
uniform sampler2D texture;
varying vec2 pass_TexCoords;
void main() {
gl_FragColor = texture2D(texture, pass_TexCoords);
}

View File

@ -0,0 +1,12 @@
attribute vec4 position;
attribute vec2 texCoords;
varying vec2 pass_TexCoords;
void main() {
gl_Position = position;
pass_TexCoords.x = texCoords.x;
pass_TexCoords.y = -texCoords.y;
}

View File

@ -0,0 +1,18 @@
uniform mat4 mvpMatrix;
uniform mat4 transformationMatrix;
attribute vec4 position;
attribute vec2 texCoords;
varying vec2 pass_TexCoords;
void main() {
vec4 transformatedPosition = transformationMatrix * position;
gl_Position = mvpMatrix * transformatedPosition;
pass_TexCoords = (transformationMatrix * vec4(texCoords, 0.0, 0.0)).xy;
pass_TexCoords *= vec2(3.0, 3.0);
pass_TexCoords.y = clamp(pass_TexCoords.y, 0.0, 1.0) + 0.01;
}

View File

@ -0,0 +1,33 @@
<?xml version="1.0" encoding="utf-8"?>
<levelPack name="Testpack">
<levels>
<level goalX="110" number="1">
<terrain endX="100" height="1.0">
<gaps></gaps>
</terrain>
<obstacles></obstacles>
</level>
<level goalX="110" number="2">
<terrain endX="100" height="-0.6">
<gaps></gaps>
</terrain>
<obstacles></obstacles>
</level>
<level goalX="110" number="3">
<terrain endX="100" height="-0.6">
<gaps>
<gap leftEdge="10" rightEdge="11" />
<gap leftEdge="20" rightEdge="21" />
<gap leftEdge="30" rightEdge="31" />
<gap leftEdge="40" rightEdge="41" />
<gap leftEdge="50" rightEdge="51" />
<gap leftEdge="60" rightEdge="61" />
<gap leftEdge="70" rightEdge="71" />
<gap leftEdge="80" rightEdge="81" />
<gap leftEdge="90" rightEdge="91" />
</gaps>
</terrain>
<obstacles></obstacles>
</level>
</levels>
</levelPack>

Binary file not shown.

After

Width:  |  Height:  |  Size: 55 KiB

View File

@ -0,0 +1,69 @@
package com.example.julian.endlessroll.data;
/**
* Created by Julian on 02.08.2016.
*/
public class Color {
private float r, g, b;
public Color() {
}
public Color(float r, float g, float b){
this.r = r;
this.g = g;
this.b = b;
}
public Color(Color other) {
this.r = other.getR();
this.g = other.getG();
this.b = other.getB();
}
public Color mix(float leftValue, float rightValue, Color color2) {
Color mySelf = new Color(this);
Color second = new Color(color2);
mySelf.mul(leftValue);
second.mul(rightValue);
mySelf.add(second);
return mySelf;
}
private void mul(float a) {
r *= a;
g *= a;
b *= a;
}
private void add(Color other) {
r += other.getR();
g += other.getG();
b += other.getB();
}
public float getR() {
return r;
}
public void setR(float r) {
this.r = r;
}
public float getG() {
return g;
}
public void setG(float g) {
this.g = g;
}
public float getB() {
return b;
}
public void setB(float b) {
this.b = b;
}
}

View File

@ -0,0 +1,101 @@
package com.example.julian.endlessroll.data;
/**
* Created by Julian on 01.12.2015.
*/
public class Vector {
public float x, y;
public Vector() {
this(0, 0);
}
public Vector(Vector other) {
this(other.x, other.y);
}
public Vector(float x, float y) {
set(x, y);
}
@Override
public String toString() {
return "Vector(" + x + ", " + y + ")";
}
public Vector set(float x, float y) {
this.x = x;
this.y = y;
return this;
}
public float length() {
return (float) Math.sqrt(x * x + y * y);
}
public Vector normalize() {
float length = this.length();
x /= length;
y /= length;
return this;
}
public Vector translate(Vector other) {
this.x += other.x;
this.y += other.y;
return this;
}
public Vector translate(float x, float y) {
this.x += x;
this.y += y;
return this;
}
public Vector mul(float z) {
x *= z;
y *= z;
return this;
}
public Vector mul(Vector other) {
this.x *= other.x;
this.y *= other.y;
return this;
}
public Vector mul(float x, float y) {
this.x *= x;
this.y *= y;
return this;
}
public Vector negate() {
this.x *= -1;
this.y *= -1;
return this;
}
public Vector vectorTo(Vector other) {
float x = other.x - this.x;
float y = other.y - this.y;
return new Vector(x, y);
}
public void setX(float x) {
this.x = x;
}
public void setY(float y) {
this.y = y;
}
public float getX() {
return x;
}
public float getY() {
return y;
}
}

View File

@ -0,0 +1,51 @@
package com.example.julian.endlessroll.entities;
import com.example.julian.endlessroll.main.game.Timer;
/**
* Created by Julian on 14.12.2015.
*/
public class Animation {
private int[] indexSequence = {0, 1, 2, 3};
private boolean looping = false;
private int requiredDelta = 110;
private int indexPointer = 0;
private boolean stillRunning = true;
private long lastSwitchTime = -1;
public void update(Timer timer) {
if (lastSwitchTime == -1) {
lastSwitchTime = timer.getCurrentTime();
return;
}
if (stillRunning) {
long delta = timer.getCurrentTime() - lastSwitchTime;
if (delta >= requiredDelta) {
lastSwitchTime = timer.getCurrentTime();
indexPointer++;
if (!looping && indexPointer == indexSequence.length - 1)
stillRunning = false;
if (looping && indexPointer == indexSequence.length)
indexPointer = 0;
}
}
}
public int getCurrentTexIndex() {
return indexSequence[indexPointer];
}
public void setIndexSequence(int[] indexSequence) {
this.indexSequence = indexSequence;
}
public void setRequiredDelta(int requiredDelta) {
this.requiredDelta = requiredDelta;
}
public void setLooping(boolean looping) {
this.looping = looping;
}
}

View File

@ -0,0 +1,45 @@
package com.example.julian.endlessroll.entities;
import com.example.julian.endlessroll.data.Vector;
import com.example.julian.endlessroll.entities.textures.Texture;
import java.util.ArrayList;
/**
* Created by Julian on 20.07.2016.
*/
public class Background extends ArrayList<Entity> {
private final float PART_WIDTH = 5;
private final float HALF_PART_WIDTH = PART_WIDTH / 2;
private Texture texture;
public Background(Texture texture) {
this.texture = texture;
super.add(createPart(-HALF_PART_WIDTH));
}
private Entity createPart(float xLeftEdge) {
return new Entity(texture, new Vector(xLeftEdge + HALF_PART_WIDTH, 0), PART_WIDTH, 2);
}
public void move(float x, float cameraX) {
Vector movement = new Vector(x, 0);
for (Entity part : this)
part.move(movement);
if (!super.isEmpty()) {
Entity last = super.get(super.size()-1);
if (last.getRightEdge() -cameraX < 3) {
super.add(createPart(last.getRightEdge()-0.001f));
}if(super.get(0).getRightEdge() -cameraX< -3){
super.remove(0);
}
}
}
public void resetPosition() {
super.clear();
super.add(createPart(-HALF_PART_WIDTH));
}
}

View File

@ -0,0 +1,37 @@
package com.example.julian.endlessroll.entities;
import android.support.annotation.Nullable;
import com.example.julian.endlessroll.data.Vector;
import com.example.julian.endlessroll.entities.particles.ParticleEffect;
import com.example.julian.endlessroll.entities.particles.ParticleSource;
import com.example.julian.endlessroll.entities.particles.ParticleSystem;
/**
* Created by Julian on 11.03.2016.
*/
public enum DestroyEffect {
EXPLOSION, STAR_EXPLOSION, NONE;
@Nullable
public ParticleSource createEffect(ParticleSystem system, Vector position, Vector size) {
if (this == NONE)
return null;
ParticleSource source = new ParticleSource(position, getEffect(system));
source.setSpawnSize(size);
return source;
}
private ParticleEffect getEffect(ParticleSystem system) {
switch (this) {
case EXPLOSION:
return system.explosion;
case STAR_EXPLOSION:
return system.starCollect;
default:
return null;
}
}
}

View File

@ -0,0 +1,81 @@
package com.example.julian.endlessroll.entities;
import com.example.julian.endlessroll.data.Vector;
import com.example.julian.endlessroll.entities.collision.geometry.Quad;
import com.example.julian.endlessroll.entities.textures.Texture;
/**
* Created by Julian on 20.11.2015.
*/
public class Entity extends Quad {
private Texture texture;
private Vector movement;
private float rotation;
private float alpha = 1.0f;
private boolean destroyed;
private DestroyEffect destroyEffect;
public Entity(Texture texture, Vector position, float width, float height) {
super(position, width, height);
this.texture = texture;
this.movement = new Vector();
}
public void move(Vector movement) {
position.translate(movement);
}
public void rotate(float factor) {
rotation += factor;
}
public void setToTerrain(float terrainHeight) {
position.y = terrainHeight + height / 2;
}
public Texture getTexture() {
return texture;
}
public void setTexture(Texture texture) {
this.texture = texture;
}
public Vector getMovement() {
return movement;
}
public void setMovement(Vector movement) {
this.movement = movement;
}
public float getRotation() {
return rotation;
}
public void setRotation(float rotation) {
this.rotation = rotation;
}
public void setAlpha(float alpha) {
this.alpha = alpha;
}
public float getAlpha() {
return alpha;
}
public void destroy(DestroyEffect destroyEffect) {
this.destroyed = true;
this.destroyEffect = destroyEffect;
}
public boolean isDestroyed() {
return destroyed;
}
public DestroyEffect getDestroyEffect() {
return destroyEffect;
}
}

View File

@ -0,0 +1,15 @@
package com.example.julian.endlessroll.entities;
import com.example.julian.endlessroll.data.Vector;
import com.example.julian.endlessroll.entities.textures.Texture;
public class Goal extends Entity {
public Goal(Texture texture) {
super(texture, new Vector(), 0.1f, 2);
}
public void setGoalX(float goalX) {
super.setPosition(new Vector(goalX - 0.05f, 0));
}
}

View File

@ -0,0 +1,18 @@
package com.example.julian.endlessroll.entities;
import com.example.julian.endlessroll.data.Vector;
import com.example.julian.endlessroll.entities.textures.Texture;
import com.example.julian.endlessroll.levels.ObstacleData;
/**
* Created by Julian on 20.11.2015.
*/
public class Obstacle extends Entity {
public Obstacle(Texture texture, ObstacleData data, float terrainHeight) {
super(texture, new Vector(data.getX(), data.getY()), data.getWidth(), data.getHeight());
if (data.isAttachedToGround())
super.setToTerrain(terrainHeight);
}
}

View File

@ -0,0 +1,41 @@
package com.example.julian.endlessroll.entities;
import com.example.julian.endlessroll.data.Vector;
import com.example.julian.endlessroll.entities.textures.Texture;
/**
* Created by Julian on 20.11.2015.
*/
public class Player extends Entity {
private final float ROTATION_SPEED = -400;
public final float RADIUS = 0.1f;
private final float START_X = -0.9f;
private float speed = 0.001f;
public Player(Texture texture) {
super(texture, new Vector(), 0, 0);
super.setWidth(RADIUS * 2);
super.setHeight(RADIUS * 2);
}
public void init(float terrainHeight) {
super.setToTerrain(terrainHeight);
super.getPosition().x = START_X;
super.setMovement(new Vector(speed, 0));
}
public void setSpeed(float speed) {
this.speed = speed;
}
public float getProgress() {
return getPosition().x - START_X;
}
@Override
public void move(Vector movement) {
super.move(movement);
rotate(movement.x * ROTATION_SPEED);
}
}

View File

@ -0,0 +1,19 @@
package com.example.julian.endlessroll.entities;
import com.example.julian.endlessroll.data.Vector;
import com.example.julian.endlessroll.entities.textures.Texture;
import com.example.julian.endlessroll.levels.StarData;
public class Star extends Entity {
private int index;
public Star(Texture texture, StarData starData) {
super(texture, new Vector(starData.getX(), starData.getY()), starData.getWidth(), starData.getHeight());
this.index = starData.getIndex();
}
public int getIndex() {
return index;
}
}

View File

@ -0,0 +1,78 @@
package com.example.julian.endlessroll.entities;
import com.example.julian.endlessroll.data.Vector;
import com.example.julian.endlessroll.entities.textures.Texture;
import com.example.julian.endlessroll.levels.Gap;
import com.example.julian.endlessroll.levels.TerrainData;
import java.util.ArrayList;
import java.util.List;
/**
* Created by Julian on 08.12.2015.
*/
public class Terrain extends ArrayList<TerrainTile> {
private Texture texture;
private float height;
private boolean endless;
public Terrain(Texture texture) {
this.texture = texture;
}
private void create(float endX, float height, List<Gap> gaps) {
this.height = height;
float y = calculateYPositionFromHeight();
float h = 1 + height;
float lastGapRightEdge = -3;
for (int i = 0; i < gaps.size() + 1; i++) {
float nextGapLeftEdge;
if (i == gaps.size())
nextGapLeftEdge = endX;
else
nextGapLeftEdge = gaps.get(i).getLeftEdge();
float width = nextGapLeftEdge - lastGapRightEdge;
float x = lastGapRightEdge + width / 2;
TerrainTile entity = new TerrainTile(texture, new Vector(x, y), width, h);
super.add(entity);
if (i != gaps.size())
lastGapRightEdge = gaps.get(i).getRightEdge();
}
}
public void loadData(TerrainData data) {
super.clear();
this.endless = false;
create(data.getEndX(), data.getHeight(), data.getGaps());
}
public void createEndless(float height) {
super.clear();
this.endless = true;
this.height = height;
super.add(new TerrainTile(texture, new Vector(0, calculateYPositionFromHeight()), 5, 1 + height));
}
public void update(float cameraX) {
if (!super.isEmpty()) {
if (super.get(0).getRightEdge() - cameraX < -3) {
super.remove(0);
}
if (endless) {
Entity last = super.get(super.size() - 1);
if (last.getRightEdge() - cameraX < 3)
super.add(new TerrainTile(texture, new Vector(last.getRightEdge() + 2.5f, calculateYPositionFromHeight()), 5, 1 + height));
}
}
}
private float calculateYPositionFromHeight() {
return height - (1 + height) / 2;
}
public float getHeight() {
return height;
}
}

View File

@ -0,0 +1,15 @@
package com.example.julian.endlessroll.entities;
import com.example.julian.endlessroll.data.Vector;
import com.example.julian.endlessroll.entities.textures.Texture;
/**
* Created by Julian on 18.12.2015.
*/
public class TerrainTile extends Entity {
public TerrainTile(Texture texture, Vector position, float width, float height) {
super(texture, position, width, height);
}
}

View File

@ -0,0 +1,78 @@
package com.example.julian.endlessroll.entities.collision;
import com.example.julian.endlessroll.data.Vector;
import com.example.julian.endlessroll.entities.collision.geometry.Circle;
import com.example.julian.endlessroll.entities.collision.geometry.Triangle;
/**
* Created by Julian on 28.02.2016.
*/
public class CircleTriangleCollisionDetector {
public boolean circleTriangleCollision(Circle circle, Triangle triangle) {
if (circleIntersectingWithTriangleVertices(circle, triangle))
return true;
if (circleCenterInsideTriangle(circle, triangle))
return true;
if (circleIntersectingWithTriangleEdges(circle, triangle))
return true;
return false;
}
private boolean circleIntersectingWithTriangleEdges(Circle circle, Triangle triangle) {
Vector edge1 = triangle.getVertex1().vectorTo(triangle.getVertex2());
Vector edge2 = triangle.getVertex2().vectorTo(triangle.getVertex3());
Vector edge3 = triangle.getVertex3().vectorTo(triangle.getVertex1());
boolean intersectingWithEdge1 = circleIntersectingWithTriangleEdge(circle, triangle.getVertex1(), edge1);
boolean intersectingWithEdge2 = circleIntersectingWithTriangleEdge(circle, triangle.getVertex2(), edge2);
boolean intersectingWithEdge3 = circleIntersectingWithTriangleEdge(circle, triangle.getVertex3(), edge3);
return intersectingWithEdge1 || intersectingWithEdge2 || intersectingWithEdge3;
}
private boolean circleIntersectingWithTriangleEdge(Circle circle, Vector vertex, Vector edge) {
Vector vertexToCenter = vertex.vectorTo(circle.getCenter());
Vector kVector = new Vector(vertexToCenter).mul(edge);
float k = kVector.x + kVector.y;
if (k > 0) {
float length = edge.length();
k = k / length;
if (k < length)
if (Math.sqrt(vertexToCenter.x * vertexToCenter.x + vertexToCenter.y * vertexToCenter.y - k * k) <= circle.getRadius())
return true;
}
return false;
}
private boolean circleCenterInsideTriangle(Circle circle, Triangle triangle) {
Vector vertex1To2 = triangle.getVertex1().vectorTo(triangle.getVertex2());
Vector vertex2To3 = triangle.getVertex2().vectorTo(triangle.getVertex3());
Vector vertex3To1 = triangle.getVertex3().vectorTo(triangle.getVertex1());
Vector vertex1ToCenter = triangle.getVertex1().vectorTo(circle.getCenter());
Vector vertex2ToCenter = triangle.getVertex2().vectorTo(circle.getCenter());
Vector vertex3ToCenter = triangle.getVertex3().vectorTo(circle.getCenter());
boolean centerInsideV1V2 = vertex1To2.y * vertex1ToCenter.x - vertex1To2.x * vertex1ToCenter.y < 0;
boolean centerInsideV2V3 = vertex2To3.y * vertex2ToCenter.x - vertex2To3.x * vertex2ToCenter.y < 0;
boolean centerInsideV3V1 = vertex3To1.y * vertex3ToCenter.x - vertex3To1.x * vertex3ToCenter.y < 0;
return centerInsideV1V2 && centerInsideV2V3 && centerInsideV3V1;
}
private boolean circleIntersectingWithTriangleVertices(Circle circle, Triangle triangle) {
boolean intersectingWithVertex1 = circleIntersectingWithTriangleVertex(circle, triangle.getVertex1());
boolean intersectingWithVertex2 = circleIntersectingWithTriangleVertex(circle, triangle.getVertex2());
boolean intersectingWithVertex3 = circleIntersectingWithTriangleVertex(circle, triangle.getVertex3());
return intersectingWithVertex1 || intersectingWithVertex2 || intersectingWithVertex3;
}
private boolean circleIntersectingWithTriangleVertex(Circle circle, Vector vertex) {
Vector centerToVertex = circle.getCenter().vectorTo(vertex);
return centerToVertex.length() <= circle.getRadius();
}
}

View File

@ -0,0 +1,126 @@
package com.example.julian.endlessroll.entities.collision;
import com.example.julian.endlessroll.data.Vector;
import com.example.julian.endlessroll.entities.Entity;
import com.example.julian.endlessroll.entities.Player;
import com.example.julian.endlessroll.entities.collision.collisionData.EntityCollisionData;
import com.example.julian.endlessroll.entities.collision.geometry.Circle;
import com.example.julian.endlessroll.entities.collision.geometry.Geometry;
import com.example.julian.endlessroll.entities.collision.geometry.Quad;
import com.example.julian.endlessroll.entities.collision.geometry.Triangle;
/**
* Created by Julian on 01.12.2015.
*/
public class CollisionDetector {
private CircleTriangleCollisionDetector triangleDetector;
public CollisionDetector() {
triangleDetector = new CircleTriangleCollisionDetector();
}
public boolean quadQuadCollision(Quad q1, Quad q2) {
float xDistance = Math.abs(q2.getPosition().x - q1.getPosition().x);
float yDistance = Math.abs(q2.getPosition().y - q1.getPosition().y);
if (xDistance >= q1.getWidth() / 2 + q2.getWidth() / 2)
return false;
if (yDistance >= q1.getHeight() / 2 + q2.getHeight() / 2)
return false;
return true;
}
public EntityCollisionData playerEntityCollision(Player player, Entity entity) {
Circle circle = new Circle(player);
Quad quad = entity;
if (circleQuadCollision(circle, quad)) {
Edge edge = circleQuadCollisionEdge(circle, player.getMovement(), quad, entity.getMovement());
return new EntityCollisionData(entity, edge);
}
return new EntityCollisionData(null, null);
}
public boolean circleToolCollision(Circle circle, Geometry bounds) {
if (bounds instanceof Circle)
return circleCircleCollision(circle, (Circle) bounds);
else if (bounds instanceof Quad)
return circleQuadCollision(circle, (Quad) bounds);
else if (bounds instanceof Triangle)
return triangleDetector.circleTriangleCollision(circle, (Triangle) bounds);
return false;
}
private boolean circleCircleCollision(Circle c1, Circle c2) {
float distance = Math.abs(c1.getCenter().vectorTo(c2.getCenter()).length());
float radiusSum = c1.getRadius() + c2.getRadius();
return distance < radiusSum;
}
private boolean circleQuadCollision(Circle circle, Quad quad) {
Vector distance = circle.getCenter().vectorTo(quad.getPosition());
distance.x = Math.abs(distance.x);
distance.y = Math.abs(distance.y);
if (distance.x > circle.getRadius() + quad.getWidth() / 2) return false;
if (distance.y > circle.getRadius() + quad.getHeight() / 2) return false;
if (distance.x <= quad.getWidth() / 2) return true;
if (distance.y <= quad.getHeight() / 2) return true;
float cornerDistance_sq = (distance.x - quad.getWidth() / 2) * (distance.x - quad.getWidth() / 2) + (distance.y - quad.getHeight() / 2) * (distance.y - quad.getHeight() / 2);
return cornerDistance_sq <= circle.getRadius() * circle.getRadius();
}
private Edge circleQuadCollisionEdge(Circle circle, Vector circleMovement, Quad quad, Vector quadMovement) {
Vector relativeMovement = circleMovement.translate(quadMovement);
//LEFT || TOP || BOTTOM
if (relativeMovement.x > 0) {
//LEFT || BOTTOM
if (relativeMovement.y > 0) {
float toLeftDistance = quad.getLeftEdge() - circle.getCenter().x;
float actualY = toLeftDistance * (relativeMovement.y / relativeMovement.x) + circle.getCenter().y;
if (actualY < quad.getBottomEdge())
return Edge.BOTTOM;
else
return Edge.LEFT;
}
//LEFT || TOP
else if (relativeMovement.y < 0) {
float toLeftDistance = quad.getLeftEdge() - circle.getCenter().x;
float actualY = toLeftDistance * (relativeMovement.y / relativeMovement.x) + circle.getCenter().y;
if (actualY < quad.getTopEdge())
return Edge.LEFT;
else
return Edge.TOP;
} else return Edge.LEFT;
}
//RIGHT || TOP || BOTTOM
else if (relativeMovement.x < 0) {
//RIGHT || BOTTOM
if (relativeMovement.y > 0) {
float toRightDistance = quad.getRightEdge() - circle.getCenter().x;
float actualY = toRightDistance * (relativeMovement.y / relativeMovement.x) + circle.getCenter().y;
if (actualY < quad.getBottomEdge())
return Edge.BOTTOM;
else
return Edge.RIGHT;
}
//RIGHT || TOP
else if (relativeMovement.y < 0) {
float toRightDistance = quad.getRightEdge() - circle.getCenter().x;
float actualY = toRightDistance * (relativeMovement.y / relativeMovement.x) + circle.getCenter().y;
if (actualY < quad.getTopEdge())
return Edge.RIGHT;
else
return Edge.TOP;
} else return Edge.RIGHT;
} else {
if (relativeMovement.y > 0)
return Edge.BOTTOM;
else if (relativeMovement.y < 0)
return Edge.TOP;
}
return Edge.NONE;
}
}

View File

@ -0,0 +1,76 @@
package com.example.julian.endlessroll.entities.collision;
import com.example.julian.endlessroll.entities.Player;
import com.example.julian.endlessroll.entities.Star;
import com.example.julian.endlessroll.entities.collision.collisionData.EntityCollisionData;
import com.example.julian.endlessroll.entities.collision.collisionData.ObstacleCollisionData;
import com.example.julian.endlessroll.entities.collision.collisionData.PlayerCollisionData;
import com.example.julian.endlessroll.entities.collision.collisionData.ToolCollisionData;
import com.example.julian.endlessroll.entities.tools.Tool;
import com.example.julian.endlessroll.main.game.Game;
import com.example.julian.endlessroll.main.game.GameScene;
import com.example.julian.endlessroll.main.game.Physics;
/**
* Created by Julian on 02.01.2016.
*/
public class CollisionManager {
private Game game;
private Player player;
public CollisionManager(Game game) {
this.game = game;
}
//Check Obstacle always before tool
public void update(Physics physics, GameScene scene) {
this.player = scene.getPlayer();
PlayerCollisionData data = physics.getPlayerCollisionData(scene);
if (data.isTerrainCollision())
checkTerrainCollision(data.getTerrainCollisionData());
if (data.isObstacleCollision())
checkObstacleCollision(data.getObstacleCollisionData());
if (data.isToolCollision())
checkToolCollision(data.getToolCollisionData());
if (data.isStarCollision())
game.onStarCollision((Star) data.getStarCollisionData().getEntity());
}
private void checkTerrainCollision(EntityCollisionData data) {
checkEntityCollision(data, -0.01f);
if (data.getEdge() != Edge.TOP)
game.onGameOver(true);
}
private void checkToolCollision(ToolCollisionData data) {
for (Tool tool : data.getTools())
tool.onPlayerCollision(player);
}
private void checkObstacleCollision(ObstacleCollisionData data) {
for (EntityCollisionData entityData : data.getCollisions()) {
checkEntityCollision(entityData, 0);
if (entityData.getEdge() != Edge.TOP)
game.onGameOver(true);
}
}
private void checkEntityCollision(EntityCollisionData data, float xBounceFactor) {
switch (data.getEdge()) {
case TOP:
player.getMovement().y = 0;
player.setToTerrain(data.getEntity().getTopEdge());
break;
case LEFT:
player.getMovement().x *= xBounceFactor;
player.getPosition().x = data.getEntity().getLeftEdge() - player.RADIUS;
break;
case RIGHT:
player.getMovement().x *= xBounceFactor;
player.getPosition().x = data.getEntity().getRightEdge() + player.RADIUS;
break;
}
}
}

View File

@ -0,0 +1,5 @@
package com.example.julian.endlessroll.entities.collision;
public enum Edge {
LEFT, RIGHT, TOP, BOTTOM, NONE;
}

View File

@ -0,0 +1,30 @@
package com.example.julian.endlessroll.entities.collision.collisionData;
import com.example.julian.endlessroll.entities.Entity;
import com.example.julian.endlessroll.entities.collision.Edge;
/**
* Created by Julian on 01.01.2016.
*/
public class EntityCollisionData {
private Entity entity;
private Edge edge;
public EntityCollisionData(Entity entity, Edge edge) {
this.entity = entity;
this.edge = edge;
}
public boolean isCollision() {
return entity != null && edge != null;
}
public Entity getEntity() {
return entity;
}
public Edge getEdge() {
return edge;
}
}

View File

@ -0,0 +1,23 @@
package com.example.julian.endlessroll.entities.collision.collisionData;
import java.util.List;
/**
* Created by Julian on 04.01.2016.
*/
public class ObstacleCollisionData {
private List<EntityCollisionData> collisions;
public ObstacleCollisionData(List<EntityCollisionData> collisions) {
this.collisions = collisions;
}
public boolean isCollision() {
return collisions.size() > 0;
}
public List<EntityCollisionData> getCollisions() {
return collisions;
}
}

View File

@ -0,0 +1,51 @@
package com.example.julian.endlessroll.entities.collision.collisionData;
/**
* Created by Julian on 05.12.2015.
*/
public class PlayerCollisionData {
private EntityCollisionData terrainCollision;
private ObstacleCollisionData obstacleCollision;
private ToolCollisionData toolCollision;
private EntityCollisionData starCollision;
public PlayerCollisionData(EntityCollisionData terrainCollision, ObstacleCollisionData obstacleCollision, ToolCollisionData toolCollision, EntityCollisionData starCollision) {
this.terrainCollision = terrainCollision;
this.obstacleCollision = obstacleCollision;
this.toolCollision = toolCollision;
this.starCollision = starCollision;
}
public boolean isTerrainCollision() {
return terrainCollision.isCollision();
}
public EntityCollisionData getTerrainCollisionData() {
return terrainCollision;
}
public boolean isObstacleCollision() {
return obstacleCollision.isCollision();
}
public ObstacleCollisionData getObstacleCollisionData() {
return obstacleCollision;
}
public boolean isToolCollision() {
return toolCollision.isCollision();
}
public ToolCollisionData getToolCollisionData() {
return toolCollision;
}
public boolean isStarCollision() {
return starCollision.isCollision();
}
public EntityCollisionData getStarCollisionData() {
return starCollision;
}
}

View File

@ -0,0 +1,25 @@
package com.example.julian.endlessroll.entities.collision.collisionData;
import com.example.julian.endlessroll.entities.tools.Tool;
import java.util.List;
/**
* Created by Julian on 21.02.2016.
*/
public class ToolCollisionData {
private List<Tool> tools;
public ToolCollisionData(List<Tool> tools) {
this.tools = tools;
}
public boolean isCollision() {
return tools.size() > 0;
}
public List<Tool> getTools() {
return tools;
}
}

View File

@ -0,0 +1,38 @@
package com.example.julian.endlessroll.entities.collision.geometry;
import com.example.julian.endlessroll.data.Vector;
import com.example.julian.endlessroll.entities.Player;
/**
* Created by Julian on 01.12.2015.
*/
public class Circle implements Geometry {
private Vector center;
private float radius;
public Circle(Player ball) {
this(new Vector(ball.getPosition()), ball.getWidth() / 2);
}
public Circle(Vector center, float radius) {
this.center = center;
this.radius = radius;
}
public Vector getCenter() {
return center;
}
public void setCenter(Vector center) {
this.center = center;
}
public float getRadius() {
return radius;
}
public void setRadius(float radius) {
this.radius = radius;
}
}

View File

@ -0,0 +1,7 @@
package com.example.julian.endlessroll.entities.collision.geometry;
/**
* Created by Julian on 28.02.2016.
*/
public interface Geometry {
}

View File

@ -0,0 +1,74 @@
package com.example.julian.endlessroll.entities.collision.geometry;
import com.example.julian.endlessroll.data.Vector;
import com.example.julian.endlessroll.entities.collision.Edge;
/**
* Created by Julian on 01.12.2015.
*/
public class Quad implements Geometry {
protected Vector position;
protected float width, height;
public Quad(Vector position, float width, float height) {
this.position = position;
this.width = width;
this.height = height;
}
public float getRightEdge() {
return position.x + width / 2;
}
public float getLeftEdge() {
return position.x - width / 2;
}
public float getTopEdge() {
return position.y + height / 2;
}
public float getBottomEdge() {
return position.y - height / 2;
}
public float getEdge(Edge edge) {
switch (edge) {
case LEFT:
return getLeftEdge();
case RIGHT:
return getRightEdge();
case TOP:
return getTopEdge();
case BOTTOM:
return getBottomEdge();
}
return -1;
}
public Vector getPosition() {
return position;
}
public void setPosition(Vector position) {
this.position = position;
}
public float getWidth() {
return width;
}
public void setWidth(float width) {
this.width = width;
}
public float getHeight() {
return height;
}
public void setHeight(float height) {
this.height = height;
}
}

View File

@ -0,0 +1,51 @@
package com.example.julian.endlessroll.entities.collision.geometry;
import com.example.julian.endlessroll.data.Vector;
import com.example.julian.endlessroll.entities.tools.Ramp;
/**
* Created by Julian on 01.12.2015.
*/
public class Triangle implements Geometry {
private Vector vertex1, vertex2, vertex3;
public Triangle(Ramp ramp) {
Vector vertex1 = new Vector(ramp.getRightEdge(), ramp.getBottomEdge());
Vector vertex2 = new Vector(ramp.getRightEdge(), ramp.getTopEdge());
Vector vertex3 = new Vector(ramp.getLeftEdge(), ramp.getBottomEdge());
setVertex1(vertex1);
setVertex2(vertex2);
setVertex3(vertex3);
}
public Triangle(Vector vertex1, Vector vertex2, Vector vertex3) {
this.vertex1 = vertex1;
this.vertex2 = vertex2;
this.vertex3 = vertex3;
}
public Vector getVertex1() {
return vertex1;
}
public void setVertex1(Vector vertex1) {
this.vertex1 = vertex1;
}
public Vector getVertex2() {
return vertex2;
}
public void setVertex2(Vector vertex2) {
this.vertex2 = vertex2;
}
public Vector getVertex3() {
return vertex3;
}
public void setVertex3(Vector vertex3) {
this.vertex3 = vertex3;
}
}

View File

@ -0,0 +1,98 @@
package com.example.julian.endlessroll.entities.particles;
import com.example.julian.endlessroll.data.Color;
import com.example.julian.endlessroll.data.Vector;
import com.example.julian.endlessroll.entities.Entity;
import com.example.julian.endlessroll.entities.particles.attributes.attributeValues.Range;
import com.example.julian.endlessroll.entities.particles.attributes.attributeValues.Timeline;
import com.example.julian.endlessroll.entities.particles.attributes.attributeValues.TintTimeline;
import com.example.julian.endlessroll.main.game.Timer;
import java.util.Random;
/**
* Created by Julian on 02.08.2016.
*/
public class Particle extends Entity {
private Color color;
private Random random;
private boolean active;
private float maxLife;
private float passedLifetime;
private Timeline scaleTimeline;
private Range scale;
private Timeline velocityTimeline;
private Range velocity;
private Timeline angleTimeline;
private Range angle;
private Timeline rotationTimeline;
private Range rotation;
private Timeline transparencyTimeline;
private TintTimeline tintTimeline;
public Particle(Random random) {
super(null, new Vector(), 1, 1);
this.random = random;
}
public void activate(Vector position, float liveValue, ParticleData particleData) {
active = true;
passedLifetime = 0;
super.setPosition(position);
maxLife = particleData.getLife().createValue(random, liveValue);
scaleTimeline = particleData.getScaleTR().getTimeline();
scale = particleData.getScaleTR().getRange().createNormalizedInstance(random);
velocityTimeline = particleData.getVelocityTR().getTimeline();
velocity = particleData.getVelocityTR().getRange().createNormalizedInstance(random);
angleTimeline = particleData.getAngleTR().getTimeline();
angle = particleData.getAngleTR().getRange().createNormalizedInstance(random);
rotationTimeline = particleData.getRotationTR().getTimeline();
rotation = particleData.getRotationTR().getRange().createNormalizedInstance(random);
transparencyTimeline = particleData.getTransparencyT();
tintTimeline = particleData.getTint();
}
public void update(Timer timer, float windStrength, float gravityStrength) {
if (active) {
passedLifetime += timer.getFrameTime();
if (passedLifetime >= maxLife)
active = false;
float lifetimePercent = passedLifetime / maxLife;
setScale(scale.createValue(random, scaleTimeline.getValueAtTime(lifetimePercent)));
setMovement(velocity.createValue(random, velocityTimeline.getValueAtTime(lifetimePercent)),
angle.createValue(random, angleTimeline.getValueAtTime(lifetimePercent)), windStrength, gravityStrength);
super.setRotation(-rotation.createValue(random, rotationTimeline.getValueAtTime(lifetimePercent)));
super.setAlpha(transparencyTimeline.getValueAtTime(lifetimePercent));
setColor(tintTimeline.getValueAtTime(lifetimePercent));
}
}
private void setScale(float scale) {
super.setWidth(scale * ParticleSystem.TRANSFER_VALUE);
super.setHeight(scale * ParticleSystem.TRANSFER_VALUE);
}
private void setMovement(float velocity, float angle, float windStrength, float gravityStrength) {
float radians = (float) Math.toRadians(angle);
Vector normalMovement = new Vector();
normalMovement.setX((float) Math.cos(radians));
normalMovement.setY((float) Math.sin(radians));
normalMovement.mul(velocity * ParticleSystem.TRANSFER_VALUE);
normalMovement.translate(windStrength * ParticleSystem.TRANSFER_VALUE, gravityStrength * ParticleSystem.TRANSFER_VALUE);
super.setMovement(normalMovement);
}
public boolean isActive() {
return active;
}
public void setColor(Color color) {
this.color = color;
}
public Color getColor() {
return color;
}
}

View File

@ -0,0 +1,58 @@
package com.example.julian.endlessroll.entities.particles;
import com.example.julian.endlessroll.entities.particles.attributes.attributeValues.Range;
import com.example.julian.endlessroll.entities.particles.attributes.attributeValues.Timeline;
import com.example.julian.endlessroll.entities.particles.attributes.attributeValues.TimelineRange;
import com.example.julian.endlessroll.entities.particles.attributes.attributeValues.TintTimeline;
/**
* Created by Julian on 03.08.2016.
*/
public class ParticleData {
private Range life;
private TimelineRange scaleTR;
private TimelineRange velocityTR;
private TimelineRange angleTR;
private TimelineRange rotationTR;
private Timeline transparencyT;
private TintTimeline tint;
public ParticleData(Range life, TimelineRange scaleTR, TimelineRange velocityTR, TimelineRange angleTR, TimelineRange rotationTR, Timeline transparencyT, TintTimeline tint) {
this.life = life;
this.scaleTR = scaleTR;
this.velocityTR = velocityTR;
this.angleTR = angleTR;
this.rotationTR = rotationTR;
this.transparencyT = transparencyT;
this.tint = tint;
}
public Range getLife() {
return life;
}
public TimelineRange getScaleTR() {
return scaleTR;
}
public TimelineRange getVelocityTR() {
return velocityTR;
}
public TimelineRange getAngleTR() {
return angleTR;
}
public TimelineRange getRotationTR() {
return rotationTR;
}
public Timeline getTransparencyT() {
return transparencyT;
}
public TintTimeline getTint() {
return tint;
}
}

View File

@ -0,0 +1,224 @@
package com.example.julian.endlessroll.entities.particles;
import com.example.julian.endlessroll.entities.particles.attributes.attributeValues.Options;
import com.example.julian.endlessroll.entities.particles.attributes.attributeValues.Range;
import com.example.julian.endlessroll.entities.particles.attributes.attributeValues.SpawnShape;
import com.example.julian.endlessroll.entities.particles.attributes.attributeValues.Timeline;
import com.example.julian.endlessroll.entities.particles.attributes.attributeValues.TimelineRange;
import com.example.julian.endlessroll.entities.particles.attributes.attributeValues.TintTimeline;
import com.example.julian.endlessroll.entities.textures.Texture;
import com.example.julian.endlessroll.main.game.Timer;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
/**
* Created by Julian on 05.08.2016.
*/
public class ParticleEffect {
private TimelineRange life;
//Particle Timeline
private TimelineRange scale;
private TimelineRange velocity;
private TimelineRange angle;
private TimelineRange rotation;
private Timeline transparency;
private TintTimeline tint;
//Source Timeline
private Range delay;
private Range duration;
private TimelineRange emission;
private Range xOffset;
private Range yOffset;
private SpawnShape.Shape spawnShape;
private TimelineRange spawnWidth;
private TimelineRange spawnHeight;
private TimelineRange wind;
private TimelineRange gravity;
private Options options;
private Texture texture;
private String textureName;
private Random random;
private List<ParticleSource> sources = new ArrayList<>();
public ParticleEffect() {
this.random = new Random();
}
public void update(Timer timer) {
for (ParticleSource source : sources)
source.update(timer);
}
public ParticleData createParticleData() {
return new ParticleData(life.getRange(), scale, velocity, angle, rotation, transparency, tint);
}
public Random getRandom() {
return random;
}
public void addSource(ParticleSource source) {
sources.add(source);
}
public void setDelay(Range delay) {
this.delay = delay;
}
public void setDuration(Range duration) {
this.duration = duration;
}
public void setEmission(TimelineRange emission) {
this.emission = emission;
}
public void setLife(TimelineRange life) {
this.life = life;
}
public void setxOffset(Range xOffset) {
this.xOffset = xOffset;
}
public void setyOffset(Range yOffset) {
this.yOffset = yOffset;
}
public void setSpawnShape(SpawnShape.Shape spawnShape) {
this.spawnShape = spawnShape;
}
public void setSpawnWidth(TimelineRange spawnWidth) {
this.spawnWidth = spawnWidth;
}
public void setSpawnHeight(TimelineRange spawnHeight) {
this.spawnHeight = spawnHeight;
}
public void setScale(TimelineRange scale) {
this.scale = scale;
}
public void setVelocity(TimelineRange velocity) {
this.velocity = velocity;
}
public void setAngle(TimelineRange angle) {
this.angle = angle;
}
public void setRotation(TimelineRange rotation) {
this.rotation = rotation;
}
public void setWind(TimelineRange wind) {
this.wind = wind;
}
public void setGravity(TimelineRange gravity) {
this.gravity = gravity;
}
public void setTint(TintTimeline tint) {
this.tint = tint;
}
public void setTransparency(Timeline transparency) {
this.transparency = transparency;
}
public Timeline getTransparency() {
return transparency;
}
public TintTimeline getTint() {
return tint;
}
public void setOptions(Options options) {
this.options = options;
}
public void setTexture(Texture texture) {
this.texture = texture;
}
public void setTextureName(String textureName) {
this.textureName = textureName;
}
public String getTextureName() {
return textureName;
}
public Texture getTexture() {
return texture;
}
public Range getDelay() {
return delay;
}
public Range getDuration() {
return duration;
}
public TimelineRange getEmission() {
return emission;
}
public Options getOptions() {
return options;
}
public TimelineRange getWind() {
return wind;
}
public TimelineRange getGravity() {
return gravity;
}
public Range getxOffset() {
return xOffset;
}
public Range getyOffset() {
return yOffset;
}
public List<ParticleSource> getSources() {
return sources;
}
public TimelineRange getLife() {
return life;
}
public SpawnShape.Shape getSpawnShape() {
return spawnShape;
}
public TimelineRange getSpawnHeight() {
return spawnHeight;
}
public void deleteSources() {
for(ParticleSource source : sources)
source.kill();
sources.clear();
}
public TimelineRange getSpawnWidth() {
return spawnWidth;
}
}

View File

@ -0,0 +1,163 @@
package com.example.julian.endlessroll.entities.particles;
import android.content.Context;
import com.example.julian.endlessroll.entities.particles.attributes.Attribute;
import com.example.julian.endlessroll.entities.particles.attributes.AttributeValueReader;
import com.example.julian.endlessroll.entities.particles.attributes.ParticleAttributeType;
import com.example.julian.endlessroll.entities.particles.attributes.attributeValues.ImagePath;
import com.example.julian.endlessroll.entities.particles.attributes.attributeValues.Options;
import com.example.julian.endlessroll.entities.particles.attributes.attributeValues.ParticleAttributeValueType;
import com.example.julian.endlessroll.entities.particles.attributes.attributeValues.Range;
import com.example.julian.endlessroll.entities.particles.attributes.attributeValues.SpawnShape;
import com.example.julian.endlessroll.entities.particles.attributes.attributeValues.Timeline;
import com.example.julian.endlessroll.entities.particles.attributes.attributeValues.TimelineRange;
import com.example.julian.endlessroll.entities.particles.attributes.attributeValues.TintTimeline;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
/**
* Created by Julian on 02.08.2016.
*/
public class ParticleReader {
private Context context;
private AttributeValueReader attributeValueReader;
private List<Attribute> attributes;
private Attribute currentAttribute;
public ParticleReader(Context context) {
this.context = context;
attributeValueReader = new AttributeValueReader();
}
/**
* reads ParticleEffect from *.pe files
* !Ignores COUNT, LIFE_OFFSET!
*/
public ParticleEffect read(String filename) throws Exception {
try {
attributes = new ArrayList<>();
currentAttribute = null;
InputStream is = context.getAssets().open(filename);
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
String line;
while ((line = reader.readLine()) != null) {
line = line.trim();
handleLine(line);
}
reader.close();
return createParticleEffect();
} catch (Exception e) {
throw new Exception("Could not read particleFile: ", e);
}
}
private void handleLine(String line) throws Exception {
if (line.startsWith("- ")) {
Attribute attrib = ParticleAttributeType.getByInFileTitle(line).createInstance();
attributes.add(attrib);
currentAttribute = attrib;
} else if (currentAttribute != null)
attributeValueReader.addValueForAttribute(currentAttribute, line);
}
private ParticleEffect createParticleEffect() throws Exception {
ParticleEffect effect = new ParticleEffect();
Timeline timeline = null;
Range range = null;
for (Attribute attribute : attributes) {
switch (attribute.getType()) {
case DELAY:
effect.setDelay((Range) attribute.get(ParticleAttributeValueType.RANGE));
break;
case DURATION:
effect.setDuration((Range) attribute.get(ParticleAttributeValueType.RANGE));
break;
case COUNT:
break;
case EMISSION:
timeline = (Timeline) attribute.get(ParticleAttributeValueType.TIMELINE);
range = (Range) attribute.get(ParticleAttributeValueType.RANGE);
effect.setEmission(new TimelineRange(timeline, range));
break;
case LIFE:
timeline = (Timeline) attribute.get(ParticleAttributeValueType.TIMELINE);
range = (Range) attribute.get(ParticleAttributeValueType.RANGE);
effect.setLife(new TimelineRange(timeline, range));
break;
case LIFE_OFFSET:
break;
case X_OFFSET:
effect.setxOffset((Range) attribute.get(ParticleAttributeValueType.RANGE));
break;
case Y_OFFSET:
effect.setyOffset((Range) attribute.get(ParticleAttributeValueType.RANGE));
break;
case SPAWN_SHAPE:
effect.setSpawnShape(((SpawnShape) attribute.get(ParticleAttributeValueType.SPAWN_SHAPE)).getShape());
break;
case SPAWN_WIDTH:
timeline = (Timeline) attribute.get(ParticleAttributeValueType.TIMELINE);
range = (Range) attribute.get(ParticleAttributeValueType.RANGE);
effect.setSpawnWidth(new TimelineRange(timeline, range));
break;
case SPAWN_HEIGHT:
timeline = (Timeline) attribute.get(ParticleAttributeValueType.TIMELINE);
range = (Range) attribute.get(ParticleAttributeValueType.RANGE);
effect.setSpawnHeight(new TimelineRange(timeline, range));
break;
case SCALE:
timeline = (Timeline) attribute.get(ParticleAttributeValueType.TIMELINE);
range = (Range) attribute.get(ParticleAttributeValueType.RANGE);
effect.setScale(new TimelineRange(timeline, range));
break;
case VELOCITY:
timeline = (Timeline) attribute.get(ParticleAttributeValueType.TIMELINE);
range = (Range) attribute.get(ParticleAttributeValueType.RANGE);
effect.setVelocity(new TimelineRange(timeline, range));
break;
case ANGLE:
timeline = (Timeline) attribute.get(ParticleAttributeValueType.TIMELINE);
range = (Range) attribute.get(ParticleAttributeValueType.RANGE);
effect.setAngle(new TimelineRange(timeline, range));
break;
case ROTATION:
timeline = (Timeline) attribute.get(ParticleAttributeValueType.TIMELINE);
range = (Range) attribute.get(ParticleAttributeValueType.RANGE);
effect.setRotation(new TimelineRange(timeline, range));
break;
case WIND:
timeline = (Timeline) attribute.get(ParticleAttributeValueType.TIMELINE);
range = (Range) attribute.get(ParticleAttributeValueType.RANGE);
effect.setWind(new TimelineRange(timeline, range));
break;
case GRAVITY:
timeline = (Timeline) attribute.get(ParticleAttributeValueType.TIMELINE);
range = (Range) attribute.get(ParticleAttributeValueType.RANGE);
effect.setGravity(new TimelineRange(timeline, range));
break;
case TINT:
effect.setTint((TintTimeline) attribute.get(ParticleAttributeValueType.TINT_TIMELINE));
break;
case TRANSPARENCY:
timeline = (Timeline) attribute.get(ParticleAttributeValueType.TIMELINE);
effect.setTransparency(timeline);
break;
case OPTIONS:
effect.setOptions((Options) attribute.get(ParticleAttributeValueType.OPTIONS));
break;
case IMAGE_PATH:
String path = ((ImagePath) attribute.get(ParticleAttributeValueType.IMAGE_PATH)).getImagePath();
effect.setTextureName(path);
break;
}
}
return effect;
}
}

View File

@ -0,0 +1,163 @@
package com.example.julian.endlessroll.entities.particles;
import com.example.julian.endlessroll.data.Vector;
import com.example.julian.endlessroll.entities.particles.attributes.attributeValues.SpawnShape;
import com.example.julian.endlessroll.main.game.Timer;
import com.example.julian.endlessroll.rendering.Lock;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Random;
/**
* Created by Julian on 02.08.2016.
*/
public class ParticleSource {
private Vector position;
private ParticleEffect effect;
private Random random;
private boolean alife;
private float currentDelay;
private float lifePercent;
private float maxTime = -1;
private float passedTime;
private float emittPause;
private float passedEmittPause;
private float passedSecond;
private float windStrength;
private float gravityStrength;
private Vector spawnSize = null;
private ParticleData particleData;
private List<Particle> activeParticles = new ArrayList<>();
private List<Particle> inactiveParticles = new ArrayList<>();
private Lock activeParticleLock = new Lock();
public ParticleSource(Vector position, ParticleEffect effect) {
this.position = position;
this.effect = effect;
random = effect.getRandom();
effect.addSource(this);
}
public void start() {
alife = true;
currentDelay = effect.getDelay().createValue(random, 0);
maxTime = effect.getDuration().createValue(random, 0) + currentDelay;
passedTime = 0;
emittPause = calcEmittPause();
passedEmittPause = 0;
passedSecond = 0;
lifePercent = 0;
}
public void update(Timer timer) {
if (alife) {
passedTime += timer.getFrameTime();
lifePercent = passedTime / maxTime;
if (passedTime >= currentDelay) {
passedEmittPause += timer.getFrameTime();
calcWindAndGravity();
while (passedEmittPause >= emittPause) {
passedEmittPause -= emittPause;
emitt();
}
passedSecond += timer.getFrameTime();
if (passedSecond >= 1000) {
passedSecond -= 1000;
calcEmittPause();
}
}
if (passedTime >= maxTime)
die();
}
updateParticles(timer);
}
private void updateParticles(Timer timer) {
activeParticleLock.lock();
Iterator<Particle> iter = activeParticles.iterator();
while (iter.hasNext()) {
Particle particle = iter.next();
particle.update(timer, windStrength, gravityStrength);
if (!particle.isActive()) {
inactiveParticles.add(particle);
iter.remove();
} else {
particle.move(new Vector(particle.getMovement()).mul(timer.getFrameTime() / 1000));
}
}
activeParticleLock.unlock();
}
private void die() {
alife = false;
if (effect.getOptions().isContinuous())
start();
}
public void kill(){
alife = false;
}
public void emitt() {
if (particleData == null)
particleData = effect.createParticleData();
float xOff = effect.getxOffset().createValue(random, 0) * ParticleSystem.TRANSFER_VALUE;
float yOff = effect.getyOffset().createValue(random, 0) * ParticleSystem.TRANSFER_VALUE;
if (effect.getSpawnShape() == SpawnShape.Shape.SQUARE) {
float width, height;
if(spawnSize == null) {
width = effect.getSpawnWidth().getRange().createValue(random, effect.getSpawnWidth().getTimeline().getValueAtTime(lifePercent));
height = effect.getSpawnHeight().getRange().createValue(random, effect.getSpawnHeight().getTimeline().getValueAtTime(lifePercent));
}else{
width = spawnSize.getX() / ParticleSystem.TRANSFER_VALUE;
height = spawnSize.getY() / ParticleSystem.TRANSFER_VALUE;
}
xOff += (random.nextFloat() * width - width * 0.5f)*ParticleSystem.TRANSFER_VALUE;
yOff += (random.nextFloat() * height - height * 0.5f)*ParticleSystem.TRANSFER_VALUE;
}
setUpParticle(new Vector(position).translate(xOff, yOff));
}
private Particle setUpParticle(Vector position) {
Particle particle;
if (inactiveParticles.size() > 0)
particle = inactiveParticles.remove(0);
else
particle = new Particle(random);
particle.activate(position, effect.getLife().getTimeline().getValueAtTime(lifePercent), particleData);
activeParticleLock.lock();
activeParticles.add(particle);
activeParticleLock.unlock();
return particle;
}
private void calcWindAndGravity() {
windStrength = effect.getWind().getRange().createValue(random, effect.getWind().getTimeline().getValueAtTime(lifePercent));
gravityStrength = effect.getGravity().getRange().createValue(random, effect.getGravity().getTimeline().getValueAtTime(lifePercent));
}
private float calcEmittPause() {
float emittedPerSecond = effect.getEmission().getRange().createValue(random, effect.getEmission().getTimeline().getValueAtTime(passedTime / maxTime));
return 1000 / emittedPerSecond;
}
public Lock getActiveParticleLock() {
return activeParticleLock;
}
public List<Particle> getActiveParticles() {
return activeParticles;
}
public void setSpawnSize(Vector spawnSize) {
this.spawnSize = spawnSize;
}
}

View File

@ -0,0 +1,50 @@
package com.example.julian.endlessroll.entities.particles;
import android.content.Context;
import com.example.julian.endlessroll.entities.textures.TextureLoader;
import com.example.julian.endlessroll.main.game.Timer;
/**
* Created by Julian on 02.08.2016.
*/
public class ParticleSystem {
public static final float TRANSFER_VALUE = 0.002f;
public final ParticleEffect explosion;
public final ParticleEffect magnet;
public final ParticleEffect starCollect;
private ParticleEffect[] effects;
private TextureLoader textureLoader;
public ParticleSystem(Context context) throws Exception {
this.textureLoader = new TextureLoader(context);
ParticleReader reader = new ParticleReader(context);
explosion = reader.read("particleEffects/explosion.pe");
magnet = reader.read("particleEffects/magnet.pe");
starCollect = reader.read("particleEffects/collectStar.pe");
effects = new ParticleEffect[]{explosion, magnet, starCollect};
}
public void update(Timer timer) {
for (ParticleEffect effect : effects)
effect.update(timer);
}
public void loadTextures() throws Exception {
for (ParticleEffect effect : effects)
effect.setTexture(textureLoader.loadTexture("particleEffects/"+effect.getTextureName()));
}
public void deleteAllSources(){
for(ParticleEffect effect : effects){
effect.deleteSources();
}
}
public ParticleEffect[] getEffects() {
return effects;
}
}

View File

@ -0,0 +1,33 @@
package com.example.julian.endlessroll.entities.particles.attributes;
import com.example.julian.endlessroll.entities.particles.attributes.attributeValues.ParticleAttributeValue;
import com.example.julian.endlessroll.entities.particles.attributes.attributeValues.ParticleAttributeValueType;
import java.util.ArrayList;
import java.util.List;
/**
* Created by Julian on 02.08.2016.
*/
public class Attribute {
private ParticleAttributeType type;
private List<ParticleAttributeValue> values = new ArrayList<>();
public Attribute(ParticleAttributeType type, ParticleAttributeValueType... valueTypes) {
this.type = type;
for (ParticleAttributeValueType valueType : valueTypes)
values.add(valueType.createInstance());
}
public ParticleAttributeValue get(ParticleAttributeValueType valueType) throws Exception {
for (ParticleAttributeValue v : values)
if (v.getType() == valueType)
return v;
throw new Exception("ParticleAttributeValue with type: " + valueType + " does not exist in Attribute "+type);
}
public ParticleAttributeType getType() {
return type;
}
}

View File

@ -0,0 +1,77 @@
package com.example.julian.endlessroll.entities.particles.attributes;
import com.example.julian.endlessroll.entities.particles.attributes.attributeValues.ImagePath;
import com.example.julian.endlessroll.entities.particles.attributes.attributeValues.Options;
import com.example.julian.endlessroll.entities.particles.attributes.attributeValues.ParticleAttributeValueType;
import com.example.julian.endlessroll.entities.particles.attributes.attributeValues.Range;
import com.example.julian.endlessroll.entities.particles.attributes.attributeValues.SpawnShape;
import com.example.julian.endlessroll.entities.particles.attributes.attributeValues.Timeline;
import com.example.julian.endlessroll.entities.particles.attributes.attributeValues.TintTimeline;
/**
* Created by Julian on 02.08.2016.
*/
public class AttributeValueReader {
public void addValueForAttribute(Attribute attribute, String line) throws Exception {
//RANGE
if (line.startsWith("lowMin:") || line.startsWith("min:"))
((Range) attribute.get(ParticleAttributeValueType.RANGE)).setLowMin(parseFloat(line));
else if (line.startsWith("lowMax:") || line.startsWith("max:"))
((Range) attribute.get(ParticleAttributeValueType.RANGE)).setLowMax(parseFloat(line));
else if (line.startsWith("highMin:"))
((Range) attribute.get(ParticleAttributeValueType.RANGE)).setHighMin(parseFloat(line));
else if (line.startsWith("highMax:"))
((Range) attribute.get(ParticleAttributeValueType.RANGE)).setHighMax(parseFloat(line));
//TIMELINE
else if (!line.startsWith("scalingCount") && line.startsWith("scaling"))
((Timeline) attribute.get(ParticleAttributeValueType.TIMELINE)).setValueOfPoint(parseTimeLineIndex("scaling", line), parseFloat(line));
else if (!line.startsWith("timelineCount") && line.startsWith("timeline") && attribute.getType() != ParticleAttributeType.TINT)
((Timeline) attribute.get(ParticleAttributeValueType.TIMELINE)).setTimeOfPoint(parseTimeLineIndex("timeline", line), parseFloat(line));
//TINT_TIMELINE
else if (!line.startsWith("colorsCount") && line.startsWith("colors")) {
int index = parseTimeLineIndex("colors", line);
((TintTimeline) attribute.get(ParticleAttributeValueType.TINT_TIMELINE)).setValueOfPoint((int) (index / 3f), index % 3, parseFloat(line));
} else if (!line.startsWith("timelineCount") && line.startsWith("timeline") && attribute.getType() == ParticleAttributeType.TINT)
((TintTimeline) attribute.get(ParticleAttributeValueType.TINT_TIMELINE)).setTimeOfPoint(parseTimeLineIndex("timeline", line), parseFloat(line));
//SPAWN_SHAPE
else if (line.startsWith("shape:"))
((SpawnShape) attribute.get(ParticleAttributeValueType.SPAWN_SHAPE)).setShape(SpawnShape.Shape.byName(parseString(line)));
//OPTIONS
else if (line.startsWith("attached:"))
((Options) attribute.get(ParticleAttributeValueType.OPTIONS)).setAttached(parseBoolean(line));
else if (line.startsWith("continuous:"))
((Options) attribute.get(ParticleAttributeValueType.OPTIONS)).setContinuous(parseBoolean(line));
else if (line.startsWith("aligned:"))
((Options) attribute.get(ParticleAttributeValueType.OPTIONS)).setAligned(parseBoolean(line));
else if (line.startsWith("additive:"))
((Options) attribute.get(ParticleAttributeValueType.OPTIONS)).setAdditive(parseBoolean(line));
else if (line.startsWith("behind:"))
((Options) attribute.get(ParticleAttributeValueType.OPTIONS)).setBehind(parseBoolean(line));
else if (line.startsWith("premultipliedAlpha:"))
((Options) attribute.get(ParticleAttributeValueType.OPTIONS)).setPremultipliedAlpha(parseBoolean(line));
//IMAGE PATH
else if (attribute.getType() == ParticleAttributeType.IMAGE_PATH)
((ImagePath) attribute.get(ParticleAttributeValueType.IMAGE_PATH)).setImagePath(line);
}
private int parseTimeLineIndex(String start, String line) throws Exception {
String asString = line.split(start)[1].split(":")[0];
return Integer.parseInt(asString);
}
private float parseFloat(String line) throws Exception {
String asString = line.split(" ")[1];
return Float.parseFloat(asString);
}
private String parseString(String line) throws Exception {
return line.split(" ")[1];
}
private boolean parseBoolean(String line) throws Exception {
String asString = line.split(" ")[1];
return Boolean.parseBoolean(asString);
}
}

View File

@ -0,0 +1,55 @@
package com.example.julian.endlessroll.entities.particles.attributes;
import com.example.julian.endlessroll.entities.particles.attributes.attributeValues.ParticleAttributeValueType;
public enum ParticleAttributeType {
NONE(""),
DELAY("Delay", ParticleAttributeValueType.RANGE),
DURATION("Duration", ParticleAttributeValueType.RANGE),
COUNT("Count", ParticleAttributeValueType.RANGE),
EMISSION("Emission", ParticleAttributeValueType.RANGE, ParticleAttributeValueType.TIMELINE),
LIFE("Life", ParticleAttributeValueType.RANGE, ParticleAttributeValueType.TIMELINE),
LIFE_OFFSET("Life Offset", ParticleAttributeValueType.RANGE, ParticleAttributeValueType.TIMELINE),
X_OFFSET("X Offset", ParticleAttributeValueType.RANGE, ParticleAttributeValueType.TIMELINE),
Y_OFFSET("Y Offset", ParticleAttributeValueType.RANGE, ParticleAttributeValueType.TIMELINE),
SPAWN_SHAPE("Spawn Shape", ParticleAttributeValueType.SPAWN_SHAPE),
SPAWN_WIDTH("Spawn Width", ParticleAttributeValueType.RANGE, ParticleAttributeValueType.TIMELINE),
SPAWN_HEIGHT("Spawn Height", ParticleAttributeValueType.RANGE, ParticleAttributeValueType.TIMELINE),
SCALE("Scale", ParticleAttributeValueType.RANGE, ParticleAttributeValueType.TIMELINE),
VELOCITY("Velocity", ParticleAttributeValueType.RANGE, ParticleAttributeValueType.TIMELINE),
ANGLE("Angle", ParticleAttributeValueType.RANGE, ParticleAttributeValueType.TIMELINE),
ROTATION("Rotation", ParticleAttributeValueType.RANGE, ParticleAttributeValueType.TIMELINE),
WIND("Wind", ParticleAttributeValueType.RANGE, ParticleAttributeValueType.TIMELINE),
GRAVITY("Gravity", ParticleAttributeValueType.RANGE, ParticleAttributeValueType.TIMELINE),
TINT("Tint", ParticleAttributeValueType.TINT_TIMELINE),
TRANSPARENCY("Transparency", ParticleAttributeValueType.RANGE, ParticleAttributeValueType.TIMELINE),
OPTIONS("Options", ParticleAttributeValueType.OPTIONS),
IMAGE_PATH("Image Path", ParticleAttributeValueType.IMAGE_PATH);
private String name;
private ParticleAttributeValueType[] valueTypes;
ParticleAttributeType(String name, ParticleAttributeValueType... valueTypes) {
this.name = name;
this.valueTypes = valueTypes;
}
private String getInFileTitle() {
return "- " + name + " -";
}
public static ParticleAttributeType getByInFileTitle(String title) throws Exception {
for (ParticleAttributeType setting : values()) {
if (setting != NONE && setting.getInFileTitle().equals(title))
return setting;
}
throw new Exception("Could not find ParticleAttributeType by title: " + title);
}
public Attribute createInstance() throws Exception {
if (this == NONE)
throw new Exception("Cannot create Instance from Attribute NONE");
return new Attribute(this, valueTypes);
}
}

View File

@ -0,0 +1,21 @@
package com.example.julian.endlessroll.entities.particles.attributes.attributeValues;
/**
* Created by Julian on 02.08.2016.
*/
public class ImagePath extends ParticleAttributeValue {
private String imagePath;
public ImagePath() {
super(ParticleAttributeValueType.IMAGE_PATH);
}
public String getImagePath() {
return imagePath;
}
public void setImagePath(String imagePath) {
this.imagePath = imagePath;
}
}

View File

@ -0,0 +1,66 @@
package com.example.julian.endlessroll.entities.particles.attributes.attributeValues;
/**
* Created by Julian on 02.08.2016.
*/
public class Options extends ParticleAttributeValue {
private boolean attached;
private boolean continuous;
private boolean aligned;
private boolean additive;
private boolean behind;
private boolean premultipliedAlpha;
public Options() {
super(ParticleAttributeValueType.OPTIONS);
}
public boolean isAttached() {
return attached;
}
public void setAttached(boolean attached) {
this.attached = attached;
}
public boolean isContinuous() {
return continuous;
}
public void setContinuous(boolean continuous) {
this.continuous = continuous;
}
public boolean isAligned() {
return aligned;
}
public void setAligned(boolean aligned) {
this.aligned = aligned;
}
public boolean isAdditive() {
return additive;
}
public void setAdditive(boolean additive) {
this.additive = additive;
}
public boolean isBehind() {
return behind;
}
public void setBehind(boolean behind) {
this.behind = behind;
}
public boolean isPremultipliedAlpha() {
return premultipliedAlpha;
}
public void setPremultipliedAlpha(boolean premultipliedAlpha) {
this.premultipliedAlpha = premultipliedAlpha;
}
}

View File

@ -0,0 +1,17 @@
package com.example.julian.endlessroll.entities.particles.attributes.attributeValues;
/**
* Created by Julian on 02.08.2016.
*/
public abstract class ParticleAttributeValue {
private ParticleAttributeValueType type;
public ParticleAttributeValue(ParticleAttributeValueType type){
this.type = type;
}
public ParticleAttributeValueType getType() {
return type;
}
}

View File

@ -0,0 +1,28 @@
package com.example.julian.endlessroll.entities.particles.attributes.attributeValues;
/**
* Created by Julian on 02.08.2016.
*/
public enum ParticleAttributeValueType {
RANGE, TIMELINE, TINT_TIMELINE, SPAWN_SHAPE, OPTIONS, IMAGE_PATH;
public ParticleAttributeValue createInstance(){
switch (this){
case RANGE:
return new Range();
case TIMELINE:
return new Timeline();
case TINT_TIMELINE:
return new TintTimeline();
case SPAWN_SHAPE:
return new SpawnShape();
case OPTIONS:
return new Options();
case IMAGE_PATH:
return new ImagePath();
}
return null;
}
}

View File

@ -0,0 +1,82 @@
package com.example.julian.endlessroll.entities.particles.attributes.attributeValues;
import java.util.Random;
/**
* Created by Julian on 02.08.2016.
*/
public class Range extends ParticleAttributeValue {
private float lowMin;
private float lowMax;
private float highMin;
private float highMax;
public Range() {
super(ParticleAttributeValueType.RANGE);
}
public Range createNormalizedInstance(Random random) {
Range range = new Range();
float high = createHighValue(random);
range.setHighMax(high);
range.setHighMin(high);
float low = createLowValue(random);
range.setLowMax(low);
range.setLowMin(low);
return range;
}
public float createValue(Random random, float mix) {
if (mix == 1)
return createHighValue(random);
else if (mix == 0)
return createLowValue(random);
else {
float highValue = createHighValue(random);
float lowValue = createLowValue(random);
return mix * (highValue - lowValue) + lowValue;
}
}
private float createHighValue(Random random) {
float min = highMin;
float max = highMax;
if (min == max)
return min;
return random.nextFloat() * (max - min) + min;
}
private float createLowValue(Random random) {
float min = lowMin;
float max = lowMax;
if (min == max)
return min;
return random.nextFloat() * (max - min) + min;
}
public void setLowMin(float lowMin) {
this.lowMin = lowMin;
}
public void setLowMax(float lowMax) {
this.lowMax = lowMax;
}
public void setHighMin(float highMin) {
this.highMin = highMin;
}
public void setHighMax(float highMax) {
this.highMax = highMax;
}
private boolean isLowDifference() {
return lowMin - lowMax != 0;
}
private boolean isHighDifference() {
return highMin - highMax != 0;
}
}

View File

@ -0,0 +1,38 @@
package com.example.julian.endlessroll.entities.particles.attributes.attributeValues;
/**
* Created by Julian on 02.08.2016.
*/
public class SpawnShape extends ParticleAttributeValue {
public enum Shape {
POINT("point"), SQUARE("square");
private String name;
Shape(String name) {
this.name = name;
}
public static Shape byName(String text) throws Exception{
for(Shape shape : values())
if(shape.name.equals(text))
return shape;
throw new Exception("Shape with name \""+text+"\" does not exist");
}
}
private Shape shape;
public SpawnShape() {
super(ParticleAttributeValueType.SPAWN_SHAPE);
}
public Shape getShape() {
return shape;
}
public void setShape(Shape shape) {
this.shape = shape;
}
}

View File

@ -0,0 +1,52 @@
package com.example.julian.endlessroll.entities.particles.attributes.attributeValues;
import java.util.ArrayList;
import java.util.List;
/**
* Created by Julian on 02.08.2016.
*/
public class Timeline extends ParticleAttributeValue {
private List<TimelinePoint> points = new ArrayList<>();
public Timeline() {
super(ParticleAttributeValueType.TIMELINE);
}
public void setValueOfPoint(int index, float value) {
if (points.size() <= index) {
points.add(new TimelinePoint());
}
points.get(index).setValue(value);
}
public void setTimeOfPoint(int index, float time) {
if (points.size() <= index) {
points.add(new TimelinePoint());
}
points.get(index).setTime(time);
}
public float getValueAtTime(float time) {
TimelinePoint left = null, right = null;
for (TimelinePoint point : points) {
if (point.getTime() <= time) {
if (left == null || left.getTime() < point.getTime())
left = point;
} else if (right == null || right.getTime() > point.getTime())
right = point;
}
if (left != null) {
if (right != null) {
float leftDist = 1 - Math.abs(left.getTime() - time);
float rightDist = 1 - Math.abs(right.getTime() - time);
float totalDist = leftDist + rightDist;
return left.getValue() * (leftDist / totalDist) + right.getValue() * (rightDist / totalDist);
}
return left.getValue();
}
return 0;
}
}

View File

@ -0,0 +1,23 @@
package com.example.julian.endlessroll.entities.particles.attributes.attributeValues;
public class TimelinePoint {
private float time, value;
public float getTime() {
return time;
}
public void setTime(float time) {
this.time = time;
}
public float getValue() {
return value;
}
public void setValue(float value) {
this.value = value;
}
}

View File

@ -0,0 +1,31 @@
package com.example.julian.endlessroll.entities.particles.attributes.attributeValues;
/**
* Created by Julian on 02.08.2016.
*/
public class TimelineRange {
private Timeline timeline;
private Range range;
public TimelineRange(Timeline timeline, Range range) {
this.timeline = timeline;
this.range = range;
}
public Timeline getTimeline() {
return timeline;
}
public void setTimeline(Timeline timeline) {
this.timeline = timeline;
}
public Range getRange() {
return range;
}
public void setRange(Range range) {
this.range = range;
}
}

View File

@ -0,0 +1,57 @@
package com.example.julian.endlessroll.entities.particles.attributes.attributeValues;
import com.example.julian.endlessroll.data.Color;
import com.example.julian.endlessroll.main.GameLog;
import java.util.ArrayList;
import java.util.List;
/**
* Created by Julian on 02.08.2016.
*/
public class TintTimeline extends ParticleAttributeValue {
private List<TintTimelinePoint> points = new ArrayList<>();
public TintTimeline() {
super(ParticleAttributeValueType.TINT_TIMELINE);
}
public void setValueOfPoint(int index, int colorIndex, float value) {
GameLog.i("Set value: index="+index+"; colorIndex="+colorIndex+"; value="+value);
if (points.size() <= index) {
points.add(new TintTimelinePoint());
}
points.get(index).setValue(colorIndex, value);
}
public void setTimeOfPoint(int index, float time) {
GameLog.i("Set time: index="+index+"; time="+time);
if (points.size() <= index) {
points.add(new TintTimelinePoint());
}
points.get(index).setTime(time);
}
public Color getValueAtTime(float time) {
TintTimelinePoint left = null, right = null;
for (TintTimelinePoint point : points) {
if (point.getTime() <= time) {
if (left == null || left.getTime() < point.getTime())
left = point;
} else if (right == null || right.getTime() > point.getTime())
right = point;
}
if (left != null) {
if (right != null) {
float leftDist = 1 - Math.abs(left.getTime() - time);
float rightDist = 1 - Math.abs(right.getTime() - time);
float totalDist = leftDist + rightDist;
return left.getColor().mix((leftDist / totalDist), (rightDist / totalDist), right.getColor());
}
return left.getColor();
}
return new Color();
}
}

View File

@ -0,0 +1,33 @@
package com.example.julian.endlessroll.entities.particles.attributes.attributeValues;
import com.example.julian.endlessroll.data.Color;
public class TintTimelinePoint {
private float time;
private Color color;
public float getTime() {
return time;
}
public void setTime(float time) {
this.time = time;
}
public Color getColor() {
return color;
}
public void setValue(int colorIndex, float value) {
if (color == null)
color = new Color();
if (colorIndex == 0)
color.setR(value);
else if (colorIndex == 1)
color.setG(value);
else if (colorIndex == 2)
color.setB(value);
}
}

View File

@ -0,0 +1,44 @@
package com.example.julian.endlessroll.entities.textures;
/**
* Created by Julian on 11.12.2015.
*/
public class Texture {
private int id;
private int atlasWidth;
private int atlasHeight;
private int atlasIndex;
public Texture(int id, int atlasWidth, int atlasHeight) {
this.id = id;
this.atlasWidth = atlasWidth;
this.atlasHeight = atlasHeight;
}
public Texture(Texture other) {
this.id = other.getId();
this.atlasWidth = other.getAtlasWidth();
this.atlasHeight = other.getAtlasHeight();
}
public int getId() {
return id;
}
public int getAtlasWidth() {
return atlasWidth;
}
public int getAtlasHeight() {
return atlasHeight;
}
public int getAtlasIndex() {
return atlasIndex;
}
public void setAtlasIndex(int atlasIndex) {
this.atlasIndex = atlasIndex;
}
}

View File

@ -0,0 +1,62 @@
package com.example.julian.endlessroll.entities.textures;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.opengl.GLES20;
import android.opengl.GLUtils;
import com.example.julian.endlessroll.main.GameLog;
import java.io.InputStream;
/**
* Created by Julian on 26.11.2015.
*/
public class TextureLoader {
private Context context;
public TextureLoader(Context context) {
this.context = context;
}
public int loadTextureId(int texture, boolean isAtlas) {
Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), texture);
return loadTextureId(bitmap, isAtlas);
}
public Texture loadTexture(String inAssetsLocation) throws Exception {
InputStream is = context.getAssets().open(inAssetsLocation);
BitmapFactory.Options options = new BitmapFactory.Options();
options.inScaled = false;
Bitmap bitmap = BitmapFactory.decodeStream(is, null, options);
return new Texture(loadTextureId(bitmap, false), 1, 1);
}
private int loadTextureId(Bitmap bitmap, boolean isAtlas) {
int id = genTexture();
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, id);
if (!isAtlas) {
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
} else {
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
}
GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0);
bitmap.recycle();
GameLog.d("Texture " + id + " successfully loaded");
return id;
}
private int genTexture() {
int[] idField = new int[1];
GLES20.glGenTextures(1, idField, 0);
return idField[0];
}
}

View File

@ -0,0 +1,53 @@
package com.example.julian.endlessroll.entities.textures;
import android.content.Context;
import com.example.julian.endlessroll.R;
import com.example.julian.endlessroll.entities.tools.ToolType;
/**
* Created by Julian on 05.12.2015.
*/
public class TexturePack {
private TextureLoader loader;
public final Texture background;
public final Texture goal;
public final Texture terrain;
public final Texture playerArrow;
public final Texture player;
public final Texture obstacle;
public final Texture star;
public final Texture blueParticle;
public final Texture yellowParticle;
public final Texture redParticle;
public TexturePack(Context context) {
loader = new TextureLoader(context);
background = loadTexture(R.drawable.background);
goal = loadTexture(R.drawable.goal);
terrain = loadAtlas(R.drawable.terrain, 1, 1);
player = loadTexture(R.drawable.ball);
playerArrow = loadTexture(R.drawable.playerarrow);
obstacle = loadTexture(R.drawable.obstacle);
star = loadTexture(R.drawable.star);
blueParticle = loadTexture(R.drawable.blueparticle);
yellowParticle = loadTexture(R.drawable.yellowparticle);
redParticle = loadTexture(R.drawable.redparticle);
ToolType.loadAllToolTextures(this);
}
private Texture loadTexture(int id) {
int texId = loader.loadTextureId(id, false);
return new Texture(texId, 1, 1);
}
public Texture loadAtlas(int id, int atlasWidth, int atlasHeight) {
int texId = loader.loadTextureId(id, true);
return new Texture(texId, atlasWidth, atlasHeight);
}
}

View File

@ -0,0 +1,60 @@
package com.example.julian.endlessroll.entities.tools;
import com.example.julian.endlessroll.data.Vector;
import com.example.julian.endlessroll.entities.DestroyEffect;
import com.example.julian.endlessroll.entities.Obstacle;
import com.example.julian.endlessroll.entities.Player;
import com.example.julian.endlessroll.entities.collision.CollisionDetector;
import com.example.julian.endlessroll.entities.collision.geometry.Geometry;
import com.example.julian.endlessroll.entities.collision.geometry.Quad;
import com.example.julian.endlessroll.main.game.Timer;
import java.util.List;
/**
* Created by Julian on 20.02.2016.
*/
public class Bomb extends Tool {
public final float RANGE = 1;
private float delta;
private boolean exploding = false;
public Bomb(Vector position) {
super(ToolType.BOMB, position, .29f, .29f, false, false);
animation.setIndexSequence(new int[]{0, 1, 2});
animation.setLooping(false);
animation.setRequiredDelta(300);
}
@Override
public void update(Timer timer) {
super.update(timer);
delta += timer.getFrameTime();
if (delta >= 1000)
exploding = true;
}
@Override
public void onPlayerCollision(Player player) {
}
@Override
protected Geometry createCollisionBounds() {
return this;
}
public boolean isExploding() {
return exploding;
}
public void explode(List<Obstacle> obstacles, CollisionDetector detector) {
Quad explotionRange = new Quad(new Vector(super.getPosition()), RANGE, RANGE);
for (Obstacle obstacle : obstacles) {
if (detector.quadQuadCollision(obstacle, explotionRange))
obstacle.destroy(DestroyEffect.EXPLOSION);
}
super.destroy(DestroyEffect.EXPLOSION);
}
}

View File

@ -0,0 +1,57 @@
package com.example.julian.endlessroll.entities.tools;
import com.example.julian.endlessroll.data.Vector;
import com.example.julian.endlessroll.entities.DestroyEffect;
import com.example.julian.endlessroll.entities.Player;
import com.example.julian.endlessroll.entities.collision.geometry.Circle;
import com.example.julian.endlessroll.entities.collision.geometry.Geometry;
import com.example.julian.endlessroll.entities.particles.ParticleSource;
import com.example.julian.endlessroll.entities.particles.ParticleSystem;
import com.example.julian.endlessroll.main.game.Timer;
/**
* Created by Julian on 11.02.2016.
*/
public class Magnet extends Tool {
private ParticleSource particleSource;
public Magnet(Vector position, ParticleSystem particleSystem) {
super(ToolType.MAGNET, position, .24f, .24f, false, false);
animation.setRequiredDelta(300);
animation.setIndexSequence(new int[]{1, 1, 0});
animation.setLooping(true);
super.setFloating(true);
particleSource = new ParticleSource(new Vector(position), particleSystem.magnet);
particleSource.start();
}
@Override
public void update(Timer timer) {
super.update(timer);
}
@Override
public void destroy(DestroyEffect destroyEffect) {
super.destroy(destroyEffect);
particleSource.kill();
}
@Override
public void onPlayerCollision(Player player) {
float fromPlayerDistance = player.getPosition().vectorTo(super.getPosition()).length();
float fromPlayerYDistance = super.getPosition().y - player.getPosition().y;
float t = Math.min(2f, 1 / fromPlayerDistance);
float influenz = .00004f * t * t;
if (fromPlayerYDistance < 0) {
player.getMovement().y -= influenz;
} else if (fromPlayerYDistance > 0) {
player.getMovement().y += influenz;
}
}
@Override
protected Geometry createCollisionBounds() {
return new Circle(super.getPosition(), 2);
}
}

View File

@ -0,0 +1,63 @@
package com.example.julian.endlessroll.entities.tools;
import com.example.julian.endlessroll.data.Vector;
import com.example.julian.endlessroll.entities.Player;
import com.example.julian.endlessroll.entities.collision.geometry.Geometry;
import com.example.julian.endlessroll.entities.collision.geometry.Triangle;
import com.example.julian.endlessroll.main.game.Timer;
/**
* Created by Julian on 29.11.2015.
*/
public class Ramp extends Tool {
public Ramp(Vector position) {
super(ToolType.RAMP, position, .4f, .4f, true, true);
animation.setLooping(true);
}
public float getGradient() {
return super.getHeight() / super.getWidth();
}
public float getHeightAt(float x, boolean clamp) {
float ratio = (x - getLeftEdge()) / super.getWidth();
if (clamp) {
if (ratio < 0)
return getBottomEdge();
if (ratio > 1)
return getTopEdge();
}
return getBottomEdge() + super.getHeight() * ratio;
}
@Override
public void update(Timer timer) {
super.update(timer);
}
@Override
public void onPlayerCollision(Player player) {
float necessaryY = calcNecessaryPlayerY(player);
if (necessaryY - player.RADIUS >= super.getBottomEdge() && necessaryY + player.RADIUS <= super.getTopEdge())
player.getPosition().y = necessaryY;
float acceleration = player.getMovement().x * getGradient();
player.getMovement().y = acceleration;
}
private float calcNecessaryPlayerY(Player player) {
float normalM = -1 / getGradient();
Vector normalToCircleCenter = new Vector(-1, -normalM).normalize();
normalToCircleCenter.mul(player.RADIUS);
float normalX = player.getPosition().x - normalToCircleCenter.x;
float normalY = getHeightAt(normalX, false);
return normalY + normalToCircleCenter.y;
}
@Override
protected Geometry createCollisionBounds() {
return new Triangle(this);
}
}

View File

@ -0,0 +1,40 @@
package com.example.julian.endlessroll.entities.tools;
import com.example.julian.endlessroll.data.Vector;
import com.example.julian.endlessroll.entities.Player;
import com.example.julian.endlessroll.entities.collision.geometry.Geometry;
import com.example.julian.endlessroll.entities.collision.geometry.Quad;
import com.example.julian.endlessroll.main.game.Timer;
/**
* Created by Julian on 04.01.2016.
*/
public class Spring extends Tool {
private boolean hasYetCollided = false;
public Spring(Vector position) {
super(ToolType.SPRING, position, .3f, .35f, true, true);
animation.setIndexSequence(new int[]{1, 0, 0, 3, 3, 3, 1});
animation.setRequiredDelta(80);
}
@Override
public void update(Timer timer) {
if (hasYetCollided)
super.update(timer);
}
@Override
public void onPlayerCollision(Player player) {
if (!hasYetCollided) {
hasYetCollided = true;
player.getMovement().y = .0024f;
}
}
@Override
protected Geometry createCollisionBounds() {
return new Quad(super.getPosition(), .2f, .2f);
}
}

View File

@ -0,0 +1,55 @@
package com.example.julian.endlessroll.entities.tools;
import com.example.julian.endlessroll.data.Vector;
import com.example.julian.endlessroll.entities.Animation;
import com.example.julian.endlessroll.entities.Entity;
import com.example.julian.endlessroll.entities.Player;
import com.example.julian.endlessroll.entities.collision.geometry.Geometry;
import com.example.julian.endlessroll.main.game.Timer;
/**
* Created by Julian on 04.01.2016.
*/
public abstract class Tool extends Entity {
private boolean placedByRightEdge;
private boolean updateBounds;
private Geometry collisionBounds;
protected Animation animation;
private boolean floating = false;
public Tool(ToolType type, Vector position, float width, float height, boolean updateBounds, boolean placedByRightEdge) {
super(type.getToolTexture(), position, width, height);
this.updateBounds = updateBounds;
this.placedByRightEdge = placedByRightEdge;
animation = new Animation();
collisionBounds = createCollisionBounds();
}
public void update(Timer timer) {
animation.update(timer);
super.getTexture().setAtlasIndex(animation.getCurrentTexIndex());
}
public abstract void onPlayerCollision(Player player);
protected abstract Geometry createCollisionBounds();
public Geometry getCollisionBounds() {
if (updateBounds)
return createCollisionBounds();
return collisionBounds;
}
public void setFloating(boolean floating) {
this.floating = floating;
}
public boolean isFloating() {
return floating;
}
public boolean isPlacedByRightEdge() {
return placedByRightEdge;
}
}

View File

@ -0,0 +1,40 @@
package com.example.julian.endlessroll.entities.tools;
import com.example.julian.endlessroll.R;
/**
* Created by Julian on 16.07.2016.
*/
public class ToolSlot {
private ToolType toolType;
private boolean locked;
public ToolSlot(ToolType toolType, boolean locked){
this.toolType = toolType;
this.locked = locked;
}
public ToolType getToolType() {
return toolType;
}
public int getDrawable(){
if(locked)
return R.drawable.lockedbutton;
else
return toolType.getButtonDrawable();
}
public void setToolType(ToolType toolType) {
this.toolType = toolType;
}
public boolean isLocked() {
return locked;
}
public void setLocked(boolean locked) {
this.locked = locked;
}
}

View File

@ -0,0 +1,50 @@
package com.example.julian.endlessroll.entities.tools;
import com.example.julian.endlessroll.levels.levelup.LevelUpBounties;
import java.util.ArrayList;
import java.util.List;
/**
* Created by Julian on 15.07.2016.
*/
public class ToolSlotSettings extends ArrayList<ToolSlot> {
public ToolSlotSettings() {
this(new ToolSlot(ToolType.RAMP, false), new ToolSlot(ToolType.NONE, true), new ToolSlot(ToolType.NONE, true), new ToolSlot(ToolType.NONE, true));
}
public ToolSlotSettings(ToolSlot slot1, ToolSlot slot2, ToolSlot slot3, ToolSlot slot4) {
super(4);
super.add(slot1);
super.add(slot2);
super.add(slot3);
super.add(slot4);
}
public ToolSlotSettings(List<ToolSlot> list) {
super(list);
}
public void reset() {
super.set(0, new ToolSlot(ToolType.RAMP, false));
super.set(1, new ToolSlot(ToolType.NONE, true));
super.set(2, new ToolSlot(ToolType.NONE, true));
super.set(3, new ToolSlot(ToolType.NONE, true));
}
public void changeToolSlotType(int slot, ToolType newType) {
for (ToolSlot toolSlot : this) {
if (super.indexOf(toolSlot) == slot)
toolSlot.setToolType(newType);
else if (toolSlot.getToolType() == newType)
toolSlot.setToolType(ToolType.NONE);
}
}
public void unlockSlotsIfLevelReached(int level, LevelUpBounties levelUpBounties) {
for (int i = 0; i < 4; i++) {
super.get(i).setLocked(!levelUpBounties.isToolSlotUnlockedAtLevel(i, level));
}
}
}

View File

@ -0,0 +1,117 @@
package com.example.julian.endlessroll.entities.tools;
import android.support.annotation.Nullable;
import com.example.julian.endlessroll.R;
import com.example.julian.endlessroll.data.Vector;
import com.example.julian.endlessroll.entities.particles.ParticleSystem;
import com.example.julian.endlessroll.entities.textures.Texture;
import com.example.julian.endlessroll.entities.textures.TexturePack;
import com.example.julian.endlessroll.sounds.SoundManager;
public enum ToolType {
//Check newInstance when new Tool is added!
RAMP("Ramp", R.drawable.ramp, R.drawable.rampbutton, R.raw.ramp, 3f, 0),
SPRING("Spring", R.drawable.spring, R.drawable.springbutton, R.raw.ramp, 4f, 5),
MAGNET("Magnet", R.drawable.magnet, R.drawable.magnetbutton, R.raw.ramp, 6f, 10),
BOMB("Bomb", R.drawable.bomb, R.drawable.bombbutton, R.raw.ramp, 6f, 12),
NONE("None", -1, R.drawable.emptybutton, -1, 0, 0);
private String name;
private int toolTextureId;
private Texture toolTexture = null;
private int buttonDrawable;
private int placingSoundId;
private int placingSound = -1;
private float regenerationTime;
private int costs;
private boolean bought = false;
ToolType(String name, int toolTextureId, int buttonDrawable, int placingSoundId, float regenerationTime, int costs) {
this.name = name;
this.toolTextureId = toolTextureId;
this.buttonDrawable = buttonDrawable;
this.placingSoundId = placingSoundId;
this.regenerationTime = regenerationTime;
this.costs = costs;
}
@Nullable
public Tool newInstance(Vector position, ParticleSystem particleSystem) {
Tool tool = null;
switch (this) {
case RAMP:
tool = new Ramp(position);
break;
case SPRING:
tool = new Spring(position);
break;
case MAGNET:
tool = new Magnet(position, particleSystem);
break;
case BOMB:
tool = new Bomb(position);
break;
case NONE:
break;
}
if (tool != null && tool.isPlacedByRightEdge())
tool.move(new Vector(-tool.getWidth() / 2, 0));
return tool;
}
public void loadAllPlacingSounds(SoundManager soundManager) {
for (ToolType type : values())
type.loadPlacingSound(soundManager);
}
public static void loadAllToolTextures(TexturePack texturePack) {
for (ToolType type : values())
type.loadToolTexture(texturePack);
}
private void loadPlacingSound(SoundManager soundManager) {
if (placingSoundId == -1)
return;
placingSound = soundManager.loadSound(placingSoundId);
}
private void loadToolTexture(TexturePack texturePack) {
if (toolTextureId == -1)
return;
toolTexture = texturePack.loadAtlas(toolTextureId, 2, 2);
}
public Texture getToolTexture() {
return toolTexture;
}
public int getButtonDrawable() {
return buttonDrawable;
}
public int getPlacingSound() {
return placingSound;
}
public String getName() {
return name;
}
public void setBought(boolean bought) {
this.bought = bought;
}
public boolean isBought() {
return bought;
}
public int getCosts() {
return costs;
}
public float getRegenerationTime() {
return regenerationTime;
}
}

View File

@ -0,0 +1,22 @@
package com.example.julian.endlessroll.levels;
import org.simpleframework.xml.Attribute;
/**
* Created by Julian on 27.11.2015.
*/
public class Gap {
@Attribute
private float leftEdge;
@Attribute
private float rightEdge;
public float getLeftEdge() {
return leftEdge;
}
public float getRightEdge() {
return rightEdge;
}
}

View File

@ -0,0 +1,110 @@
package com.example.julian.endlessroll.levels;
import org.simpleframework.xml.Attribute;
import org.simpleframework.xml.Element;
import org.simpleframework.xml.ElementList;
import java.util.List;
/**
* Created by Julian on 07.12.2015.
*/
public class Level {
@Attribute
private int number;
@Attribute
private float goalX;
@Element
private TerrainData terrain;
@ElementList
private List<ObstacleData> obstacles;
@ElementList
private List<StarData> stars;
private boolean completed;
private boolean unlocked;
private boolean firstStarCollected;
private boolean secondStarCollected;
private boolean thirdStarCollected;
public int getNumber() {
return number;
}
public float getGoalX() {
return goalX;
}
public TerrainData getTerrain() {
return terrain;
}
public List<ObstacleData> getObstacles() {
return obstacles;
}
public List<StarData> getStars() {
return stars;
}
public boolean isUnlocked() {
return unlocked;
}
public void setUnlocked(boolean unlocked) {
this.unlocked = unlocked;
}
public boolean isCompleted() {
return completed;
}
public void setCompleted(boolean completed) {
this.completed = completed;
}
public boolean isFirstStarCollected() {
return firstStarCollected;
}
public boolean isSecondStarCollected() {
return secondStarCollected;
}
public boolean isThirdStarCollected() {
return thirdStarCollected;
}
public void setStarCollected(int index, boolean collected){
if(index == 1)
firstStarCollected = collected;
else if(index == 2)
secondStarCollected = collected;
else if(index == 3)
thirdStarCollected = collected;
}
public String getCollectedStars(){
String code = "";
code+= firstStarCollected?"1":"";
code+= secondStarCollected?"2":"";
code+= thirdStarCollected?"3":"";
return code;
}
public void setCollectedStars(String code){
firstStarCollected = code.contains("1");
secondStarCollected = code.contains("2");
thirdStarCollected = code.contains("3");
}
public void reset(){
completed = false;
unlocked = false;
firstStarCollected = false;
secondStarCollected = false;
thirdStarCollected = false;
}
}

View File

@ -0,0 +1,84 @@
package com.example.julian.endlessroll.levels;
import android.content.Context;
import com.example.julian.endlessroll.main.DataStorageHandler;
import com.example.julian.endlessroll.main.GameLog;
import org.simpleframework.xml.Serializer;
import org.simpleframework.xml.core.Persister;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
public class LevelManager extends ArrayList<LevelPack> {
public LevelManager(Context context, DataStorageHandler dataStorageHandler) throws Exception {
String[] assets = context.getAssets().list("levelpacks");
for (String asset : assets) {
try {
LevelPack pack = loadLevelPack(context, "levelpacks/" + asset);
dataStorageHandler.readLevelProgress(pack);
dataStorageHandler.readLevelPackLocked(pack);
pack.tryToUnlockFirstLevel();
if (pack.getId() == 0)
pack.setLocked(false);
super.add(pack);
} catch (Exception e) {
GameLog.e(e);
}
sort();
}
}
private void sort() {
Collections.sort(this, new Comparator<LevelPack>() {
@Override
public int compare(LevelPack lhs, LevelPack rhs) {
return lhs.getId() - rhs.getId();
}
});
}
private LevelPack loadLevelPack(Context context, String name) throws Exception {
try {
InputStream source = context.getAssets().open(name);
Serializer serializer = new Persister();
return serializer.read(LevelPack.class, source);
} catch (Exception e) {
throw new Exception("Could not load levelPack \"" + name + "\"", e);
}
}
public void reset() {
for (LevelPack pack : this) {
pack.reset();
if (pack.getId() != 0)
pack.setLocked(true);
}
}
public void unlockAllPacks() {
for (LevelPack levelPack : this)
levelPack.setLocked(false);
}
public void unlockAllLevels() {
for (LevelPack levelPack : this) {
for (Level level : levelPack.getLevels())
level.setUnlocked(true);
}
}
public LevelPack nextLevelPack(LevelPack old) {
int oldId = old.getId();
for (LevelPack pack : this) {
if (pack.getId() == oldId + 1)
return pack;
}
return null;
}
}

View File

@ -0,0 +1,95 @@
package com.example.julian.endlessroll.levels;
import org.simpleframework.xml.Attribute;
import org.simpleframework.xml.ElementList;
import org.simpleframework.xml.Root;
import java.util.List;
/**
* Created by Julian on 07.12.2015.
*/
@Root
public class LevelPack {
@Attribute
private String name;
@Attribute
private int id;
@ElementList
private List<Level> levels;
private boolean locked;
public String getName() {
return name;
}
public Integer getId() {
return id;
}
public List<Level> getLevels() {
return levels;
}
public int getUnlockedLevels(){
int count = 0;
for(Level level : levels)
if(level.isUnlocked())
count++;
return count;
}
public int getCollectedStars(){
int count = 0;
for(Level level : levels)
count += level.getCollectedStars().length();
return count;
}
public int getAvailableStars(){
return levels.size() * 3;
}
public void tryToUnlockFirstLevel() {
try {
levels.get(0).setUnlocked(true);
} catch (Exception e) {
}
}
public Level getLevel(int number) {
for (Level level : levels)
if (level.getNumber() == number)
return level;
return null;
}
public Level getNextLevel(Level currentLevel) {
if (isLastLevel(currentLevel)) {
return null;
}
int index = levels.indexOf(currentLevel);
return levels.get(index + 1);
}
public boolean isLastLevel(Level level) {
int index = levels.indexOf(level);
return levels.size() == index + 1;
}
public void reset(){
for(Level level : levels){
level.reset();
}
tryToUnlockFirstLevel();
}
public void setLocked(boolean locked) {
this.locked = locked;
}
public boolean isLocked() {
return locked;
}
}

View File

@ -0,0 +1,46 @@
package com.example.julian.endlessroll.levels;
import org.simpleframework.xml.Attribute;
/**
* Created by Julian on 07.12.2015.
*/
public class ObstacleData {
@Attribute
private String type;
@Attribute
private float leftEdge;
@Attribute
private float rightEdge;
@Attribute
private float height;
@Attribute
private float y;
@Attribute
public boolean attachedToGround;
public String getType() {
return type;
}
public float getX() {
return leftEdge + getWidth() / 2;
}
public float getWidth() {
return rightEdge - leftEdge;
}
public float getHeight() {
return height;
}
public float getY() {
return y;
}
public boolean isAttachedToGround() {
return attachedToGround;
}
}

View File

@ -0,0 +1,37 @@
package com.example.julian.endlessroll.levels;
import org.simpleframework.xml.Attribute;
public class StarData {
@Attribute
private int index;
@Attribute
private float x;
@Attribute
private float y;
@Attribute
private float width;
@Attribute
private float height;
public int getIndex() {
return index;
}
public float getX() {
return x;
}
public float getY() {
return y;
}
public float getWidth() {
return width;
}
public float getHeight() {
return height;
}
}

View File

@ -0,0 +1,32 @@
package com.example.julian.endlessroll.levels;
import org.simpleframework.xml.Attribute;
import org.simpleframework.xml.ElementList;
import java.util.List;
/**
* Created by Julian on 27.11.2015.
*/
public class TerrainData {
@Attribute
private float height;
@Attribute
private float endX;
@ElementList
private List<Gap> gaps;
public float getHeight() {
return height;
}
public float getEndX() {
return endX;
}
public List<Gap> getGaps() {
return gaps;
}
}

View File

@ -0,0 +1,71 @@
package com.example.julian.endlessroll.levels.levelup;
import android.content.Context;
import com.example.julian.endlessroll.entities.tools.ToolType;
import com.example.julian.endlessroll.views.BountyMessage;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* Created by Julian on 17.07.2016.
*/
public class LevelUpBounties extends HashMap<Integer, List<LevelUpBounties.Bounty>> {
public interface Bounty {
BountyMessage createMessage(Context context);
}
private Map<ToolBounty, Integer> allToolBounties = new HashMap<>();
private List<Integer> allToolSlotLevels = new ArrayList<>();
public LevelUpBounties() {
addBounties(1, new ToolBounty(ToolType.RAMP), new ToolSlotBounty());
addBounties(2, new StarBounty(5), new ToolBounty(ToolType.SPRING));
addBounties(3, new StarBounty(6), new ToolBounty(ToolType.MAGNET), new ToolSlotBounty());
addBounties(4, new StarBounty(7), new ToolBounty(ToolType.BOMB), new ToolSlotBounty());
addBounties(5, new StarBounty(8), new ToolSlotBounty());
}
private void addBounties(int unlockLevel, Bounty... bounties) {
List<Bounty> list = new ArrayList<>();
for (Bounty bounty : bounties) {
list.add(bounty);
if (bounty instanceof ToolBounty)
allToolBounties.put((ToolBounty) bounty, unlockLevel);
else if (bounty instanceof ToolSlotBounty)
allToolSlotLevels.add(unlockLevel);
}
super.put(unlockLevel, list);
}
public boolean isToolAlreadyUnlockedAtLevel(int level, ToolType toolType) {
for (ToolBounty bounty : allToolBounties.keySet())
if (bounty.getToolType() == toolType && allToolBounties.get(bounty) <= level)
return true;
return false;
}
public boolean isToolSlotUnlockedAtLevel(int toolSlotIndex, int level) {
return allToolSlotLevels.get(toolSlotIndex) <= level;
}
public int getBountyStarsAtLevel(int level) {
for (Bounty bounty : this.get(level)) {
if (bounty instanceof StarBounty)
return ((StarBounty) bounty).getStarCount();
}
return 0;
}
@Override
public List<Bounty> get(Object key) {
List<Bounty> list = super.get(key);
if (list == null)
return new ArrayList<>();
return list;
}
}

View File

@ -0,0 +1,26 @@
package com.example.julian.endlessroll.levels.levelup;
import android.content.Context;
import com.example.julian.endlessroll.views.BountyMessage;
/**
* Created by Julian on 17.07.2016.
*/
public class StarBounty implements LevelUpBounties.Bounty {
private int starCount;
public StarBounty(int starCount) {
this.starCount = starCount;
}
public int getStarCount() {
return starCount;
}
@Override
public BountyMessage createMessage(Context context) {
return new BountyMessage(context, starCount);
}
}

View File

@ -0,0 +1,27 @@
package com.example.julian.endlessroll.levels.levelup;
import android.content.Context;
import com.example.julian.endlessroll.entities.tools.ToolType;
import com.example.julian.endlessroll.views.BountyMessage;
/**
* Created by Julian on 17.07.2016.
*/
public class ToolBounty implements LevelUpBounties.Bounty {
private ToolType toolType;
public ToolBounty(ToolType toolType) {
this.toolType = toolType;
}
public ToolType getToolType() {
return toolType;
}
@Override
public BountyMessage createMessage(Context context) {
return new BountyMessage(context, toolType);
}
}

View File

@ -0,0 +1,16 @@
package com.example.julian.endlessroll.levels.levelup;
import android.content.Context;
import com.example.julian.endlessroll.views.BountyMessage;
/**
* Created by Julian on 17.07.2016.
*/
public class ToolSlotBounty implements LevelUpBounties.Bounty {
@Override
public BountyMessage createMessage(Context context) {
return new BountyMessage(context);
}
}

View File

@ -0,0 +1,12 @@
package com.example.julian.endlessroll.main;
import com.example.julian.endlessroll.main.game.User;
/**
* Created by Julian on 15.07.2016.
*/
public class DataSafer {
private User user;
}

View File

@ -0,0 +1,110 @@
package com.example.julian.endlessroll.main;
import android.app.Activity;
import android.content.Context;
import android.content.SharedPreferences;
import com.example.julian.endlessroll.entities.tools.ToolSlot;
import com.example.julian.endlessroll.entities.tools.ToolSlotSettings;
import com.example.julian.endlessroll.levels.Level;
import com.example.julian.endlessroll.levels.LevelPack;
import com.example.julian.endlessroll.main.game.User;
import com.example.julian.endlessroll.sqlDatabase.MyDatabase;
/**
* Created by Julian on 25.04.2016.
*/
public class DataStorageHandler {
private final String PREFERENCES_NAME = "GamePreferences";
private final String SOUND_ON = "Sound";
private final String USER_STARS = "Stars";
private final String USER_LEVEL = "Level";
private final String USER_LEVEL_PROGRESS = "LevelProgress";
private SharedPreferences preferences;
private MyDatabase database;
public DataStorageHandler(Activity activity) {
preferences = activity.getSharedPreferences(PREFERENCES_NAME, Context.MODE_PRIVATE);
database = new MyDatabase(activity);
}
public boolean readIsSoundOn() {
return preferences.getBoolean(SOUND_ON, true);
}
public void writeSoundOn(boolean soundOn) {
SharedPreferences.Editor editor = preferences.edit();
editor.putBoolean(SOUND_ON, soundOn);
editor.apply();
}
public User readUserData() {
int stars = preferences.getInt(USER_STARS, 0);
int level = preferences.getInt(USER_LEVEL, 1);
int levelProgress = preferences.getInt(USER_LEVEL_PROGRESS, 0);
//TODO: Default Tooltypes to NONE
database.open();
ToolSlotSettings toolSlotSettings = database.readToolSlotSettings();
database.close();
return new User(stars, level, levelProgress, toolSlotSettings);
}
public void writeUserData(User user) {
SharedPreferences.Editor editor = preferences.edit();
editor.putInt(USER_STARS, user.getStarCount());
editor.putInt(USER_LEVEL, user.getLevel());
editor.putInt(USER_LEVEL_PROGRESS, user.getLevelProgress());
editor.apply();
database.open();
for (ToolSlot toolSlot : user.getToolSlotSettings())
database.writeToolSlot(user.getToolSlotSettings().indexOf(toolSlot), toolSlot);
database.close();
}
public void writeLevelProgress(int levelpackNumber, Level level) {
database.open();
database.writeLevelProgress(levelpackNumber, level);
database.close();
}
public void writeLevelPackLocked(LevelPack levelPack) {
database.open();
database.writeLevelPackLocked(levelPack);
database.close();
}
public void readLevelPackLocked(LevelPack levelPack){
database.open();
database.readLevelPackLocked(levelPack);
database.close();
}
public void readLevelProgress(LevelPack levelPack) {
database.open();
for (Level level : levelPack.getLevels()) {
database.readLevelProgress(levelPack.getId(), level);
}
database.close();
}
public void clearLevelProgess() {
database.open();
database.clearLevelProgess();
database.close();
}
public void readBoughtTools() {
database.open();
database.readBoughtTools();
database.close();
}
public void writeBoughtTools() {
database.open();
database.writeBoughtTools();
database.close();
}
}

View File

@ -0,0 +1,10 @@
package com.example.julian.endlessroll.main;
/**
* Created by Julian on 06.02.2016.
*/
public interface ExceptionHandler {
void onException(Exception e);
}

View File

@ -0,0 +1,172 @@
package com.example.julian.endlessroll.main;
import android.app.Activity;
import android.app.ActivityManager;
import android.content.Context;
import android.content.pm.ConfigurationInfo;
import android.content.res.Configuration;
import android.graphics.Typeface;
import android.os.Bundle;
import android.view.KeyEvent;
import android.view.Window;
import android.view.WindowManager;
import android.widget.RelativeLayout;
import com.example.julian.endlessroll.levels.Level;
import com.example.julian.endlessroll.levels.LevelManager;
import com.example.julian.endlessroll.levels.LevelPack;
import com.example.julian.endlessroll.main.game.User;
import com.example.julian.endlessroll.main.screens.GameScreen;
import com.example.julian.endlessroll.main.screens.LevelsScreen;
import com.example.julian.endlessroll.main.screens.Screen;
import com.example.julian.endlessroll.main.screens.ScreenFlipper;
import com.example.julian.endlessroll.main.screens.StartScreen;
import com.example.julian.endlessroll.main.screens.ToolShopScreen;
import com.example.julian.endlessroll.main.screens.WorldsScreen;
import com.example.julian.endlessroll.rendering.renderer.GameRenderer;
import com.example.julian.endlessroll.sounds.SoundManager;
import com.example.julian.endlessroll.views.TopBarData;
/**
* Created by Julian on 06.02.2016.
*/
public class GameActivity extends Activity implements ExceptionHandler {
private DataStorageHandler dataStorageHandler;
private LevelManager levelManager;
private SoundManager soundManager;
private User user;
private MyGlSurfaceView glSurfaceView;
private ScreenFlipper flipper;
private StartScreen startScreen;
private WorldsScreen worldsScreen;
private LevelsScreen levelsScreen;
private ToolShopScreen toolShopScreen;
private GameScreen gameScreen;
@Override
protected void onCreate(Bundle savedInstanceState) {
try {
GameLog.d("OnCreate");
super.onCreate(savedInstanceState);
super.requestWindowFeature(Window.FEATURE_NO_TITLE);
super.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
if (!hasGLES20())
throw new Exception("OpenGL ES 2.0 not supported");
dataStorageHandler = new DataStorageHandler(this);
dataStorageHandler.readBoughtTools();
user = dataStorageHandler.readUserData();
soundManager = new SoundManager(this);
soundManager.setSoundOn(dataStorageHandler.readIsSoundOn());
soundManager.backgroundMusic.getPlayer().setLooping(true);
soundManager.backgroundMusic.start();
levelManager = new LevelManager(this, dataStorageHandler);
this.glSurfaceView = new MyGlSurfaceView(this, new GameRenderer(this));
Typeface typeface = Typeface.createFromAsset(getAssets(), "fontBaron.ttf");
TopBarData topBarData = new TopBarData(this, dataStorageHandler, soundManager, levelManager, user, typeface);
startScreen = new StartScreen(this, glSurfaceView, soundManager, levelManager, user, typeface);
worldsScreen = new WorldsScreen(topBarData);
levelsScreen = new LevelsScreen(topBarData);
toolShopScreen = new ToolShopScreen(topBarData);
gameScreen = new GameScreen(topBarData, glSurfaceView);
flipper = new ScreenFlipper(this, startScreen, worldsScreen, levelsScreen, gameScreen, toolShopScreen);
RelativeLayout relativeLayout = new RelativeLayout(this);
relativeLayout.addView(glSurfaceView);
relativeLayout.addView(flipper);
setContentView(relativeLayout);
} catch (Exception e) {
onException(e);
return;
}
}
public void flipToScreen(final Screen.ScreenType screen) {
runOnUiThread(new Runnable() {
@Override
public void run() {
flipper.showScreen(screen);
}
});
}
public void setToolshopCaller(Screen.ScreenType caller) {
toolShopScreen.setCaller(caller);
}
public void selectWorld(LevelPack levelPack) {
levelsScreen.createList(levelPack);
}
public void startGame(final LevelPack levelPack, final Level level) {
runOnUiThread(new Runnable() {
@Override
public void run() {
flipper.showScreen(Screen.ScreenType.GAME);
gameScreen.startGame(levelPack, level);
}
});
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
try {
if (keyCode == KeyEvent.KEYCODE_BACK) {
flipper.getCurrentScreen().onBackKeyDown();
return true;
}
} catch (Exception e) {
onException(e);
}
return super.onKeyDown(keyCode, event);
}
@Override
public void onException(Exception e) {
GameLog.e(e);
super.finish();
}
@Override
protected void onPause() {
GameLog.d("OnPause");
glSurfaceView.onPause();
if(flipper.getCurrentScreen() == gameScreen)
gameScreen.onPause();
soundManager.pause();
super.onPause();
}
@Override
protected void onResume() {
GameLog.d("OnResume");
glSurfaceView.onResume();
soundManager.resume();
super.onResume();
}
@Override
protected void onDestroy() {
GameLog.d("OnDestroy");
soundManager.destroy();
dataStorageHandler.writeSoundOn(soundManager.isSoundOn());
super.onDestroy();
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
}
private boolean hasGLES20() {
ActivityManager am = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
ConfigurationInfo info = am.getDeviceConfigurationInfo();
return info.reqGlEsVersion >= 0x20000;
}
}

View File

@ -0,0 +1,16 @@
package com.example.julian.endlessroll.main;
import android.widget.RelativeLayout;
/**
* Created by Julian on 08.12.2015.
*/
public interface GameHandler extends ExceptionHandler {
void startInUiThread(Runnable runnable);
void toLevelsScreen();
RelativeLayout getRootLayout();
}

View File

@ -0,0 +1,44 @@
package com.example.julian.endlessroll.main;
import android.util.Log;
/**
* Created by Julian on 23.11.2015.
*/
public class GameLog {
private final static String TAG = "GameLog";
public static boolean debugging = true;
public static void i(String message) {
Log.i(TAG + getCallerInfo(), message);
}
public static void d(String message) {
if (debugging)
Log.d(TAG + getCallerInfo(), message);
}
public static void e(String message) {
Log.e(TAG + getCallerInfo(), message);
}
public static void e(Throwable error) {
Log.e(TAG + getCallerInfo(), error.getMessage(), error);
}
//Possible to get Method which called i, d, e
//Method found at stack[4]
public static void stack() {
StackTraceElement[] stack = Thread.currentThread().getStackTrace();
Log.i(TAG + "Stack", "StackSize: " + stack.length);
for (int i = 0; i < stack.length; i++) {
Log.i(TAG + "Stack", i + ": " + stack[i]);
}
}
private static String getCallerInfo() {
StackTraceElement[] stack = Thread.currentThread().getStackTrace();
return "(" + stack[4].getFileName() + ", " + stack[4].getMethodName() + ", " + stack[4].getLineNumber() + ")";
}
}

View File

@ -0,0 +1,47 @@
package com.example.julian.endlessroll.main;
import android.content.Context;
import android.opengl.GLSurfaceView;
import com.example.julian.endlessroll.rendering.renderer.GameRenderer;
import com.example.julian.endlessroll.rendering.Rendering;
/**
* Created by Julian on 30.07.2016.
*/
public class MyGlSurfaceView extends GLSurfaceView {
private GameRenderer renderer;
private boolean rendererSet;
public MyGlSurfaceView(Context context, GameRenderer gameRenderer) throws Exception {
super(context);
this.renderer = gameRenderer;
super.setEGLContextClientVersion(2);
super.setRenderer(renderer);
rendererSet = true;
}
public void addRendering(Rendering rendering){
renderer.addRendering(rendering);
}
public void setCurrentRendering(Rendering currentRendering) {
super.setOnTouchListener(currentRendering);
renderer.setCurrentRendering(currentRendering);
}
@Override
public void onResume() {
GameLog.i("SurfaceView: onResume");
if (rendererSet)
super.onResume();
}
@Override
public void onPause() {
GameLog.i("SurfaceView: onPause");
if (rendererSet)
super.onPause();
}
}

View File

@ -0,0 +1,266 @@
package com.example.julian.endlessroll.main.game;
import android.view.MotionEvent;
import android.view.View;
import com.example.julian.endlessroll.data.Vector;
import com.example.julian.endlessroll.entities.DestroyEffect;
import com.example.julian.endlessroll.entities.Player;
import com.example.julian.endlessroll.entities.Star;
import com.example.julian.endlessroll.entities.collision.CollisionManager;
import com.example.julian.endlessroll.entities.particles.ParticleSystem;
import com.example.julian.endlessroll.entities.textures.TexturePack;
import com.example.julian.endlessroll.entities.tools.ToolType;
import com.example.julian.endlessroll.levels.Level;
import com.example.julian.endlessroll.levels.LevelManager;
import com.example.julian.endlessroll.levels.LevelPack;
import com.example.julian.endlessroll.levels.levelup.LevelUpBounties;
import com.example.julian.endlessroll.main.DataStorageHandler;
import com.example.julian.endlessroll.main.GameHandler;
import com.example.julian.endlessroll.main.GameLog;
import com.example.julian.endlessroll.rendering.Rendering;
import com.example.julian.endlessroll.sounds.SoundManager;
import com.example.julian.endlessroll.views.MessageType;
import com.example.julian.endlessroll.views.ToolButton;
import com.example.julian.endlessroll.views.ToolButtonBar;
import com.example.julian.endlessroll.views.TopBarData;
import com.example.julian.endlessroll.views.ViewManager;
import java.util.ArrayList;
import java.util.List;
/**
* Created by Julian on 26.11.2015.
*/
public class Game extends Rendering<GameScene> {
private User user;
private DataStorageHandler dataStorageHandler;
private LevelManager levelManager;
private GameHandler handler;
private ViewManager viewManager;
private SoundManager sounds;
private LevelPack levelPack;
private ParticleSystem particleSystem;
private LevelUpBounties levelUpBounties;
private ToolType currentTool;
private Player player;
private Physics physics;
private CollisionManager collisionManager;
private Timer timer;
private GameState gameState = GameState.PAUSED;
private Level level;
private List<Integer> collectedStars = new ArrayList<>();
public Game(GameHandler handler, TopBarData topBarData) throws Exception{
super(topBarData.getGameActivity());
this.handler = handler;
this.user = topBarData.getUser();
this.levelManager = topBarData.getLevelManager();
this.sounds = topBarData.getSoundManager();
levelUpBounties = new LevelUpBounties();
physics = new Physics();
collisionManager = new CollisionManager(this);
particleSystem = new ParticleSystem(getContext());
this.dataStorageHandler = topBarData.getDataStorageHandler();
viewManager = new ViewManager(this, handler, topBarData);
}
@Override
public GameScene init(TexturePack texturePack, Timer timer, boolean isFirstTime) {
GameLog.d("initGame");
this.timer = timer;
try {
if (isFirstTime) {
scene = new GameScene(texturePack, particleSystem);
if (level != null)
startGame(levelPack, level);
} else {
scene.setTexturePack(texturePack);
}
particleSystem.loadTextures();
} catch (Exception e) {
onException(e);
}
return scene;
}
public void startGame(LevelPack levelPack, Level level) {
GameLog.d("Start game");
try {
this.level = level;
this.levelPack = levelPack;
if (scene != null) {
collectedStars.clear();
particleSystem.deleteAllSources();
scene.loadLevel(level);
player = scene.getPlayer();
if (viewManager.isScreenSizeSet())
viewManager.resetToolButtonBar();
currentTool = viewManager.toolButtonBar.getActiveButton().getToolType();
viewManager.startCountdown();
}
} catch (Exception e) {
onException(e);
}
}
public void countdownFinished() {
gameState = GameState.RUNNING;
}
@Override
public void setScreenSize(int width, int height) {
Vector screenSize = new Vector(width, height);
scene.setScreenSize(screenSize);
viewManager.setScreenSize(screenSize);
}
@Override
public void update() {
// GameLog.d("update GAME");
particleSystem.update(timer);
float playerProgress = 0;
if (player != null)
playerProgress = player.getProgress();
viewManager.update(gameState == GameState.RUNNING, timer, playerProgress);
switch (gameState) {
case RUNNING:
if (player.getPosition().y < -2f) {
onGameOver(false);
return;
}
if (player.getPosition().x >= scene.getGoalX()) {
onGoalReached();
return;
}
physics.applyGravity(scene);
scene.update(timer);
collisionManager.update(physics, scene);
break;
}
}
@Override
public boolean onTouch(View v, MotionEvent event) {
if (gameState == GameState.RUNNING) {
ToolButtonBar bar = viewManager.toolButtonBar;
ToolButton button = bar.getByToolType(currentTool);
if (button != null && button.finishedLoading()) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
button.setProgress(0);
addTool(event.getX(), event.getY());
}
}
return true;
}
return false;
}
public void resetViews() {
viewManager.resetToolButtonBar();
}
public void continueGame() {
viewManager.hideShortMenu();
viewManager.startCountdown();
}
public void startNextLevel() {
level = levelPack.getNextLevel(level);
startGame(levelPack, level);
}
public void restartLevel() {
startGame(levelPack, level);
}
public void toLevelsScreen() {
handler.toLevelsScreen();
}
public void setCurrentTool(ToolType toolType) {
currentTool = toolType;
}
public void pause() {
viewManager.showShortMenu();
if (gameState == GameState.RUNNING) {
gameState = GameState.PAUSED;
} else {
viewManager.stopCountdown();
}
}
private void addTool(float x, float y) {
try {
sounds.playSound(currentTool.getPlacingSound());
scene.addTool(currentTool, x, y);
} catch (Exception e) {
onException(e);
}
}
public void onGameOver(boolean playerExplode) {
if (playerExplode) {
scene.remove(player);
DestroyEffect.EXPLOSION.createEffect(particleSystem, player.getPosition(), new Vector(player.getWidth(), player.getHeight())).start();
}
gameState = GameState.GAME_OVER;
viewManager.showMessage(false, MessageType.GAME_OVER);
}
private void onGoalReached() {
gameState = GameState.LEVEL_FINISHED;
if (!level.isCompleted())
user.gainLvUpExp();
level.setCompleted(true);
for (int i = 1; i <= 3; i++) {
if (collectedStars.contains(i)) {
level.setStarCollected(i, true);
user.increaseStarCount();
}
}
if (user.isShowLevelUp()) {
user.levelUpShown();
viewManager.showLevelUp(user.getLevel());
user.getToolSlotSettings().unlockSlotsIfLevelReached(user.getLevel(), levelUpBounties);
user.increaseStarCount(levelUpBounties.getBountyStarsAtLevel(user.getLevel()));
viewManager.resetToolButtonBar();
}
viewManager.showMessage(levelPack.isLastLevel(level), MessageType.WIN);
dataStorageHandler.writeLevelProgress(levelPack.getId(), level);
Level nextLevel = levelPack.getNextLevel(level);
if (nextLevel != null) {
nextLevel.setUnlocked(true);
dataStorageHandler.writeLevelProgress(levelPack.getId(), nextLevel);
}else{
LevelPack nextLevelPack = levelManager.nextLevelPack(levelPack);
if(nextLevelPack != null){
nextLevelPack.setLocked(false);
dataStorageHandler.writeLevelPackLocked(nextLevelPack);
}
}
dataStorageHandler.writeUserData(user);
}
public void onStarCollision(Star star) {
scene.onStarCollision(star);
collectedStars.add(star.getIndex());
}
@Override
public void onException(Exception e) {
handler.onException(e);
}
public GameState getGameState() {
return gameState;
}
}

View File

@ -0,0 +1,162 @@
package com.example.julian.endlessroll.main.game;
import com.example.julian.endlessroll.data.Vector;
import com.example.julian.endlessroll.entities.DestroyEffect;
import com.example.julian.endlessroll.entities.Entity;
import com.example.julian.endlessroll.entities.Goal;
import com.example.julian.endlessroll.entities.Obstacle;
import com.example.julian.endlessroll.entities.Star;
import com.example.julian.endlessroll.entities.Terrain;
import com.example.julian.endlessroll.entities.TerrainTile;
import com.example.julian.endlessroll.entities.collision.CollisionDetector;
import com.example.julian.endlessroll.entities.particles.ParticleSystem;
import com.example.julian.endlessroll.entities.textures.TexturePack;
import com.example.julian.endlessroll.entities.tools.Bomb;
import com.example.julian.endlessroll.entities.tools.Tool;
import com.example.julian.endlessroll.entities.tools.ToolType;
import com.example.julian.endlessroll.levels.Level;
import com.example.julian.endlessroll.levels.ObstacleData;
import com.example.julian.endlessroll.levels.StarData;
import com.example.julian.endlessroll.main.GameLog;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
/**
* Created by Julian on 27.11.2015.
*/
public class GameScene extends Scene {
private CollisionDetector collisionDetector;
private Goal goal;
private float goalX;
private List<Obstacle> obstacles = new ArrayList<>();
private List<Star> stars = new ArrayList<>();
private List<Tool> tools = new ArrayList<>();
public GameScene(TexturePack texturePack, ParticleSystem particleSystem) throws Exception {
super(texturePack, particleSystem);
collisionDetector = new CollisionDetector();
goal = new Goal(textures.goal);
}
public void loadLevel(Level level) throws Exception {
reset();
lock.lock();
terrain.loadData(level.getTerrain());
super.add(goal);
player.init(terrain.getHeight());
super.add(player);
lock.unlock();
for (ObstacleData data : level.getObstacles())
addObstacle(data);
for (StarData data : level.getStars()) {
if (data.getIndex() == 1 && level.isFirstStarCollected())
continue;
if (data.getIndex() == 2 && level.isSecondStarCollected())
continue;
if (data.getIndex() == 3 && level.isThirdStarCollected())
continue;
addStar(data);
}
goalX = level.getGoalX();
goal.setGoalX(goalX);
GameLog.d("Level " + level.getNumber() + " successfully loaded");
}
private void reset() {
lock.lock();
super.clear();
lock.unlock();
obstacles.clear();
tools.clear();
cameraX = 0;
background.resetPosition();
}
public void onStarCollision(Star collisionStar) {
Iterator<Star> iter = stars.iterator();
while (iter.hasNext()) {
Star star = iter.next();
if (star.equals(collisionStar)) {
star.destroy(DestroyEffect.STAR_EXPLOSION);
iter.remove();
}
}
}
public void addObstacle(ObstacleData data) {
Obstacle obstacle = new Obstacle(textures.obstacle, data, terrain.getHeight());
lock.lock();
super.add(obstacle);
obstacles.add(obstacle);
lock.unlock();
}
public void addStar(StarData data) {
Star star = new Star(textures.star, data);
lock.lock();
super.add(star);
stars.add(star);
lock.unlock();
}
public void addTool(ToolType type, float screenX, float screenY) throws Exception {
Vector position = calcWorldFromScreenCoords(screenX, screenY);
Tool tool = type.newInstance(position, particleSystem);
if (tool == null)
throw new Exception("Current ToolType(" + type + ") returns null at method newInstance()");
lock.lock();
super.add(tool);
tools.add(tool);
lock.unlock();
}
@Override
public void update(Timer timer) {
super.update(timer);
for (Tool tool : tools) {
tool.update(timer);
if (tool instanceof Bomb) {
Bomb bomb = (Bomb) tool;
if (bomb.isExploding())
bomb.explode(obstacles, collisionDetector);
}
}
}
@Override
protected void removeEntityFromAllLists(Entity entity) {
GameLog.i("REMOVE FROM ALL LISTS");
if (!entity.isDestroyed())
entity.destroy(null);
if (entity instanceof Tool)
tools.remove(entity);
if (entity instanceof Obstacle)
obstacles.remove(entity);
}
public Terrain getTerrain() {
return terrain;
}
public List<Tool> getTools() {
return tools;
}
public List<Obstacle> getObstacles() {
return obstacles;
}
public List<Star> getStars() {
return stars;
}
public float getGoalX() {
return goalX;
}
}

View File

@ -0,0 +1,10 @@
package com.example.julian.endlessroll.main.game;
/**
* Created by Julian on 02.02.2016.
*/
public enum GameState {
RUNNING, PAUSED, GAME_OVER, LEVEL_FINISHED
}

View File

@ -0,0 +1,150 @@
package com.example.julian.endlessroll.main.game;
import android.support.annotation.Nullable;
import com.example.julian.endlessroll.entities.Entity;
import com.example.julian.endlessroll.entities.Obstacle;
import com.example.julian.endlessroll.entities.Star;
import com.example.julian.endlessroll.entities.Terrain;
import com.example.julian.endlessroll.entities.TerrainTile;
import com.example.julian.endlessroll.entities.collision.CollisionDetector;
import com.example.julian.endlessroll.entities.collision.collisionData.EntityCollisionData;
import com.example.julian.endlessroll.entities.collision.collisionData.ObstacleCollisionData;
import com.example.julian.endlessroll.entities.collision.collisionData.PlayerCollisionData;
import com.example.julian.endlessroll.entities.collision.collisionData.ToolCollisionData;
import com.example.julian.endlessroll.entities.collision.geometry.Circle;
import com.example.julian.endlessroll.entities.tools.Bomb;
import com.example.julian.endlessroll.entities.tools.Tool;
import com.example.julian.endlessroll.main.GameLog;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* Created by Julian on 27.11.2015.
*/
public class Physics {
public final float GRAVITY_FORCE = .00004f;
private CollisionDetector detector;
public Physics() {
detector = new CollisionDetector();
}
public void applyGravity(GameScene scene) {
scene.getPlayer().getMovement().y -= GRAVITY_FORCE;
for (Tool tool : scene.getTools()) {
if (tool.isFloating())
continue;
if (tool instanceof Bomb) {
for (Obstacle obstacle : scene.getObstacles()) {
if (detector.quadQuadCollision(obstacle, tool)) {
GameLog.i("collision");
tool.setFloating(true);
tool.getMovement().y = 0;
break;
}
}
if (tool.isFloating())
continue;
}
float terrainHeight = getTerrainHeight(tool, scene.getTerrain());
Obstacle toolIsOver = getObstacleToolIsOver(tool, scene.getObstacles());
float orientingHeight = terrainHeight;
if (toolIsOver != null) {
if (toolIsOver.getBottomEdge() < tool.getTopEdge())
orientingHeight = Math.max(toolIsOver.getTopEdge(), terrainHeight);
else{
orientingHeight = terrainHeight;
}
}
if (tool.getBottomEdge() > orientingHeight) {
tool.getMovement().y -= GRAVITY_FORCE * 2;
} else {
tool.getMovement().y = 0;
tool.setToTerrain(orientingHeight);
}
}
}
@Nullable
private Obstacle getObstacleToolIsOver(Entity tool, List<Obstacle> obstacles) {
Map<Float, Obstacle> isOver = new HashMap<>();
for (Obstacle obstacle : obstacles) {
if ((tool.getLeftEdge() >= obstacle.getLeftEdge() && tool.getLeftEdge() <= obstacle.getRightEdge()) || (tool.getRightEdge() <= obstacle.getRightEdge() && tool.getRightEdge() >= obstacle.getLeftEdge()))
isOver.put(obstacle.getTopEdge(), obstacle);
}
float max = -100;
for (float height : isOver.keySet()) {
if(isOver.get(height).getBottomEdge() < tool.getTopEdge()) {
max = Math.max(max, height);
}
}
if (max != -100)
return isOver.get(max);
return null;
}
private float getTerrainHeight(Entity tool, Terrain terrain) {
for (TerrainTile instance : terrain) {
if ((tool.getLeftEdge() >= instance.getLeftEdge() && tool.getLeftEdge() <= instance.getRightEdge())
|| (tool.getRightEdge() <= instance.getRightEdge() && tool.getRightEdge() >= instance.getLeftEdge())
|| (instance.getLeftEdge() >= tool.getLeftEdge() && instance.getLeftEdge() <= tool.getRightEdge())
|| (instance.getRightEdge() <= tool.getRightEdge() && instance.getRightEdge() >= tool.getLeftEdge()))
return terrain.getHeight();
}
return -10;
}
public PlayerCollisionData getPlayerCollisionData(GameScene scene) {
EntityCollisionData terrainData = playerCollidesWithTerrain(scene);
ObstacleCollisionData obstacleData = playerCollidesWithObstacle(scene);
ToolCollisionData toolData = playerCollidesWithTool(scene);
EntityCollisionData starData = playerCollidesWithStar(scene);
return new PlayerCollisionData(terrainData, obstacleData, toolData, starData);
}
private EntityCollisionData playerCollidesWithTerrain(GameScene scene) {
Terrain terrain = scene.getTerrain();
for (TerrainTile terrainTile : terrain) {
EntityCollisionData data = detector.playerEntityCollision(scene.getPlayer(), terrainTile);
if (data.isCollision())
return data;
}
return new EntityCollisionData(null, null);
}
private ObstacleCollisionData playerCollidesWithObstacle(GameScene scene) {
List<EntityCollisionData> collisions = new ArrayList<>();
for (Obstacle obstacle : scene.getObstacles()) {
EntityCollisionData data = detector.playerEntityCollision(scene.getPlayer(), obstacle);
if (data.isCollision())
collisions.add(data);
}
return new ObstacleCollisionData(collisions);
}
private ToolCollisionData playerCollidesWithTool(GameScene scene) {
List<Tool> tools = new ArrayList<>();
Circle circle = new Circle(scene.getPlayer());
for (Tool tool : scene.getTools()) {
if (detector.circleToolCollision(circle, tool.getCollisionBounds()))
tools.add(tool);
}
return new ToolCollisionData(tools);
}
private EntityCollisionData playerCollidesWithStar(GameScene scene) {
for (Star star : scene.getStars()) {
EntityCollisionData data = detector.playerEntityCollision(scene.getPlayer(), star);
if (data.isCollision())
return data;
}
return new EntityCollisionData(null, null);
}
}

View File

@ -0,0 +1,120 @@
package com.example.julian.endlessroll.main.game;
import com.example.julian.endlessroll.data.Vector;
import com.example.julian.endlessroll.entities.Background;
import com.example.julian.endlessroll.entities.Entity;
import com.example.julian.endlessroll.entities.Player;
import com.example.julian.endlessroll.entities.Terrain;
import com.example.julian.endlessroll.entities.particles.ParticleSystem;
import com.example.julian.endlessroll.entities.textures.TexturePack;
import com.example.julian.endlessroll.rendering.Lock;
import java.util.ArrayList;
import java.util.Iterator;
/**
* Created by Julian on 20.07.2016.
*/
public abstract class Scene extends ArrayList<Entity> {
public float cameraX;
public final Lock lock;
private Vector screenSize;
private Entity playerArrow;
protected ParticleSystem particleSystem;
protected TexturePack textures;
protected Background background;
protected Terrain terrain;
protected Player player;
public Scene(TexturePack texturePack, ParticleSystem particleSystem) {
this.particleSystem = particleSystem;
setTexturePack(texturePack);
playerArrow = new Entity(textures.playerArrow, new Vector(0, 0.9f), .2f, .2f);
background = new Background(textures.background);
terrain = new Terrain(textures.terrain);
player = new Player(textures.player);
lock = new Lock();
}
public void setTexturePack(TexturePack texturePack) {
this.textures = texturePack;
}
public void update(Timer timer) {
lock.lock();
Iterator<Entity> iterator = super.iterator();
while (iterator.hasNext()) {
Entity entity = iterator.next();
Vector movement = entity.getMovement();
Vector finalMovement = new Vector(movement).mul(timer.getFrameTime());
entity.move(finalMovement);
if (entity.isDestroyed() && entity.getDestroyEffect() != null)
entity.getDestroyEffect().createEffect(particleSystem, new Vector(entity.getPosition()), new Vector(entity.getWidth(), entity.getHeight())).start();
if (entity.equals(player))
moveEnviroment(finalMovement.x);
else if (entity.getRightEdge() - cameraX < -3f || entity.isDestroyed()) {
iterator.remove();
removeEntityFromAllLists(entity);
}
}
if (player.getPosition().y >= player.RADIUS + 1) {
playerArrow.getPosition().x = player.getPosition().x;
if (!super.contains(playerArrow)) {
super.add(playerArrow);
}
} else super.remove(playerArrow);
lock.unlock();
}
@Override
public boolean remove(Object object) {
removeEntityFromAllLists((Entity) object);
return super.remove(object);
}
protected abstract void removeEntityFromAllLists(Entity entity);
private void moveEnviroment(float x) {
cameraX += x;
background.move(x * 0.95f, cameraX);
terrain.update(cameraX);
}
protected Vector calcWorldFromScreenCoords(float screenX, float screenY) throws Exception {
if (screenSize == null)
throw new Exception("ScreenSize not set");
float glCoordWidth = (2f * screenSize.x / screenSize.y);
float x = ((screenX / screenSize.x) * 2f - 1f) * glCoordWidth / 2;
x += cameraX;
float y = -((screenY / screenSize.y) * 2f - 1f);
return new Vector(x, y);
}
public void setScreenSize(Vector screenSize) {
this.screenSize = screenSize;
}
public Background getBackground() {
return background;
}
public Terrain getTerrain() {
return terrain;
}
public Player getPlayer() {
return player;
}
public TexturePack getTextures() {
return textures;
}
public ParticleSystem getParticleSystem() {
return particleSystem;
}
}

View File

@ -0,0 +1,19 @@
package com.example.julian.endlessroll.main.game;
import com.example.julian.endlessroll.entities.Entity;
import com.example.julian.endlessroll.entities.particles.ParticleSystem;
import com.example.julian.endlessroll.entities.textures.TexturePack;
public class StartScene extends Scene {
public StartScene(TexturePack texturePack, ParticleSystem particleSystem) {
super(texturePack, particleSystem);
terrain.createEndless(-.8f);
player.init(terrain.getHeight());
super.add(player);
}
@Override
protected void removeEntityFromAllLists(Entity entity) {
}
}

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