Initial commit.

This commit is contained in:
Woody Folsom
2012-03-06 11:42:35 -05:00
commit 8e83234a87
124 changed files with 9621 additions and 0 deletions

8
.gitignore vendored Normal file
View File

@@ -0,0 +1,8 @@
bin
build
classes
dist
docs
.project
.settings
.classpath

261
DetailedInfo.txt Normal file
View File

@@ -0,0 +1,261 @@
StartTime = -17
RightMove: StTime = 94 EdTime = 32
Jump: StTime = 119 EdTime = 132
Jump: StTime = 139 EdTime = 155
RightMove: StTime = 128 EdTime = 64
RightMove: StTime = 161 EdTime = 65
Jump: StTime = 158 EdTime = 170
CollectCoin: time = 176
CollectCoin: time = 177
Jump: StTime = 176 EdTime = 184
RightMove: StTime = 163 EdTime = 89
BlockCoinDestroy: time = 190
Jump: StTime = 188 EdTime = 196
BlockPowerDestroy: time = 208
Jump: StTime = 206 EdTime = 214
RightMove: StTime = 200 EdTime = 112
LeftMove: StTime = 224 EdTime = 2
RightMove: StTime = 227 EdTime = 125
Jump: StTime = 234 EdTime = 248
LittleState: StTime = -17 EdTime = 251
LeftMove: StTime = 241 EdTime = 31
StompKill: EnemyType = 2 time = 286
Jump: StTime = 271 EdTime = 297
Jump: StTime = 302 EdTime = 312
Jump: StTime = 325 EdTime = 344
RightMove: StTime = 271 EdTime = 200
RightMove: StTime = 347 EdTime = 201
RightMove: StTime = 352 EdTime = 202
Jump: StTime = 352 EdTime = 364
CollectCoin: time = 372
CollectCoin: time = 375
Jump: StTime = 392 EdTime = 407
LargeState: StTime = 251 EdTime = 407
RightMove: StTime = 354 EdTime = 294
RightMove: StTime = 447 EdTime = 295
RightMove: StTime = 449 EdTime = 296
Jump: StTime = 448 EdTime = 457
RightMove: StTime = 451 EdTime = 328
RightMove: StTime = 484 EdTime = 329
RightMove: StTime = 486 EdTime = 330
Jump: StTime = 484 EdTime = 494
CollectCoin: time = 519
CollectCoin: time = 519
CollectCoin: time = 522
Jump: StTime = 519 EdTime = 527
CollectCoin: time = 530
CollectCoin: time = 532
BlockCoinDestroy: time = 532
Jump: StTime = 530 EdTime = 538
RightMove: StTime = 488 EdTime = 385
Jump: StTime = 545 EdTime = 553
LeftMove: StTime = 544 EdTime = 45
BlockCoinDestroy: time = 560
Jump: StTime = 558 EdTime = 566
RightMove: StTime = 559 EdTime = 396
Jump: StTime = 570 EdTime = 578
LeftMove: StTime = 571 EdTime = 54
RightMove: StTime = 581 EdTime = 398
Jump: StTime = 590 EdTime = 598
LeftMove: StTime = 584 EdTime = 71
RightMove: StTime = 602 EdTime = 403
Jump: StTime = 603 EdTime = 611
Jump: StTime = 614 EdTime = 622
Jump: StTime = 626 EdTime = 634
LeftMove: StTime = 608 EdTime = 98
RightMove: StTime = 636 EdTime = 433
RightMove: StTime = 667 EdTime = 434
Jump: StTime = 664 EdTime = 676
RightMove: StTime = 669 EdTime = 442
RightMove: StTime = 681 EdTime = 443
RightMove: StTime = 683 EdTime = 444
Jump: StTime = 681 EdTime = 694
CollectCoin: time = 716
CollectCoin: time = 718
CollectCoin: time = 725
CollectCoin: time = 725
Jump: StTime = 716 EdTime = 729
CollectCoin: time = 733
CollectCoin: time = 741
Jump: StTime = 731 EdTime = 744
Jump: StTime = 751 EdTime = 765
Jump: StTime = 801 EdTime = 811
CollectCoin: time = 821
CollectCoin: time = 821
RightMove: StTime = 685 EdTime = 583
Jump: StTime = 821 EdTime = 829
BlockCoinDestroy: time = 836
Jump: StTime = 834 EdTime = 842
LeftMove: StTime = 832 EdTime = 111
CollectCoin: time = 850
LeftMove: StTime = 846 EdTime = 124
CollectCoin: time = 859
Jump: StTime = 850 EdTime = 863
Jump: StTime = 864 EdTime = 872
RightMove: StTime = 860 EdTime = 600
Jump: StTime = 880 EdTime = 888
BlockPowerDestroy: time = 895
Jump: StTime = 893 EdTime = 901
RightMove: StTime = 882 EdTime = 624
LittleState: StTime = 407 EdTime = 919
Jump: StTime = 915 EdTime = 951
BlockPowerDestroy: time = 973
CollectCoin: time = 974
CollectCoin: time = 977
Jump: StTime = 972 EdTime = 978
CollectCoin: time = 982
Jump: StTime = 984 EdTime = 990
RightMove: StTime = 912 EdTime = 709
Jump: StTime = 996 EdTime = 1010
Jump: StTime = 1018 EdTime = 1024
BlockCoinDestroy: time = 1030
Jump: StTime = 1029 EdTime = 1035
LeftMove: StTime = 1012 EdTime = 148
LeftMove: StTime = 1039 EdTime = 165
LargeState: StTime = 919 EdTime = 1060
Jump: StTime = 1054 EdTime = 1081
RightMove: StTime = 1057 EdTime = 749
LeftMove: StTime = 1098 EdTime = 167
Jump: StTime = 1105 EdTime = 1117
StompKill: EnemyType = 2 time = 1133
Jump: StTime = 1119 EdTime = 1144
RunState: StTime = 1144 EdTime = 1148
RunState: StTime = 1158 EdTime = 1162
RightMove: StTime = 1169 EdTime = 751
RightMove: StTime = 1172 EdTime = 753
Jump: StTime = 1165 EdTime = 1175
RightMove: StTime = 1183 EdTime = 757
LeftMove: StTime = 1188 EdTime = 172
RightMove: StTime = 1194 EdTime = 758
RightMove: StTime = 1196 EdTime = 759
BlockCoinDestroy: time = 1206
Jump: StTime = 1205 EdTime = 1211
Jump: StTime = 1221 EdTime = 1227
RightMove: StTime = 1203 EdTime = 792
Jump: StTime = 1233 EdTime = 1245
CollectCoin: time = 1259
Jump: StTime = 1262 EdTime = 1268
RightMove: StTime = 1237 EdTime = 824
Jump: StTime = 1278 EdTime = 1284
RightMove: StTime = 1291 EdTime = 832
Jump: StTime = 1293 EdTime = 1306
CollectCoin: time = 1309
Jump: StTime = 1311 EdTime = 1317
CollectCoin: time = 1322
Jump: StTime = 1325 EdTime = 1331
CollectCoin: time = 1331
Jump: StTime = 1340 EdTime = 1346
Jump: StTime = 1356 EdTime = 1371
Jump: StTime = 1378 EdTime = 1391
Jump: StTime = 1401 EdTime = 1413
Jump: StTime = 1456 EdTime = 1468
Jump: StTime = 1509 EdTime = 1522
Jump: StTime = 1533 EdTime = 1545
Jump: StTime = 1560 EdTime = 1579
RightMove: StTime = 1309 EdTime = 1104
LeftMove: StTime = 1582 EdTime = 183
Jump: StTime = 1594 EdTime = 1609
Jump: StTime = 1616 EdTime = 1628
Jump: StTime = 1630 EdTime = 1640
Jump: StTime = 1647 EdTime = 1667
Jump: StTime = 1671 EdTime = 1683
Jump: StTime = 1722 EdTime = 1734
Jump: StTime = 1738 EdTime = 1752
CollectCoin: time = 1752
CollectCoin: time = 1754
CollectCoin: time = 1757
CollectCoin: time = 1769
CollectCoin: time = 1772
FireState: StTime = 1060 EdTime = 1773
CollectCoin: time = 1793
CollectCoin: time = 1796
CollectCoin: time = 1799
CollectCoin: time = 1802
Jump: StTime = 1799 EdTime = 1805
RightMove: StTime = 1594 EdTime = 1321
Jump: StTime = 1812 EdTime = 1818
BlockCoinDestroy: time = 1824
Jump: StTime = 1823 EdTime = 1829
RightMove: StTime = 1821 EdTime = 1339
Jump: StTime = 1835 EdTime = 1841
Jump: StTime = 1851 EdTime = 1857
RightMove: StTime = 1845 EdTime = 1359
StompKill: EnemyType = 2 time = 1883
RightMove: StTime = 1867 EdTime = 1383
Jump: StTime = 1869 EdTime = 1894
CollectCoin: time = 1900
CollectCoin: time = 1904
Jump: StTime = 1903 EdTime = 1909
BlockPowerDestroy: time = 1914
Jump: StTime = 1913 EdTime = 1919
RightMove: StTime = 1892 EdTime = 1413
Jump: StTime = 1929 EdTime = 1935
RightMove: StTime = 1923 EdTime = 1431
LargeState: StTime = 1773 EdTime = 1948
LeftMove: StTime = 1942 EdTime = 210
Jump: StTime = 1943 EdTime = 1976
LeftMove: StTime = 1976 EdTime = 215
StompKill: EnemyType = 2 time = 1984
Jump: StTime = 1980 EdTime = 1995
RightMove: StTime = 1982 EdTime = 1447
Jump: StTime = 2009 EdTime = 2024
Jump: StTime = 2046 EdTime = 2059
Jump: StTime = 2083 EdTime = 2096
RunState: StTime = 2122 EdTime = 2126
RunState: StTime = 2148 EdTime = 2151
Jump: StTime = 2139 EdTime = 2155
RunState: StTime = 2156 EdTime = 2159
RunState: StTime = 2163 EdTime = 2166
RunState: StTime = 2170 EdTime = 2173
LeftMove: StTime = 2028 EdTime = 372
Jump: StTime = 2202 EdTime = 2218
Jump: StTime = 2224 EdTime = 2236
LeftMove: StTime = 2232 EdTime = 378
RunState: StTime = 2294 EdTime = 2297
RightMove: StTime = 2239 EdTime = 1511
RunState: StTime = 2316 EdTime = 2319
RunState: StTime = 2323 EdTime = 2326
RunState: StTime = 2330 EdTime = 2333
RunState: StTime = 2336 EdTime = 2339
RightMove: StTime = 2332 EdTime = 1519
RunState: StTime = 2346 EdTime = 2348
FireKill: EnemyType =2time = 2349
RunState: StTime = 2350 EdTime = 2353
LeftMove: StTime = 2344 EdTime = 387
RunState: StTime = 2356 EdTime = 2357
RunState: StTime = 2362 EdTime = 2365
RunState: StTime = 2367 EdTime = 2371
RunState: StTime = 2373 EdTime = 2376
RunState: StTime = 2377 EdTime = 2381
RightMove: StTime = 2385 EdTime = 1543
RightMove: StTime = 2410 EdTime = 1544
RightMove: StTime = 2412 EdTime = 1545
RightMove: StTime = 2414 EdTime = 1546
RightMove: StTime = 2416 EdTime = 1547
RightMove: StTime = 2418 EdTime = 1559
Jump: StTime = 2416 EdTime = 2431
RightMove: StTime = 2431 EdTime = 1560
RightMove: StTime = 2433 EdTime = 1561
RightMove: StTime = 2435 EdTime = 1562
RightMove: StTime = 2437 EdTime = 1563
RightMove: StTime = 2439 EdTime = 1564
RightMove: StTime = 2441 EdTime = 1565
RightMove: StTime = 2443 EdTime = 1566
Jump: StTime = 2441 EdTime = 2451
Jump: StTime = 2457 EdTime = 2472
Jump: StTime = 2506 EdTime = 2512
Jump: StTime = 2540 EdTime = 2546
RightMove: StTime = 2445 EdTime = 1676
Jump: StTime = 2570 EdTime = 2576
LeftMove: StTime = 2556 EdTime = 408
RightMove: StTime = 2578 EdTime = 1684
Jump: StTime = 2593 EdTime = 2599
LeftMove: StTime = 2587 EdTime = 424
RightMove: StTime = 2604 EdTime = 1705
RightMove: StTime = 2626 EdTime = 1706
RightMove: StTime = 2628 EdTime = 1707
Jump: StTime = 2627 EdTime = 2642
Jump: StTime = 2651 EdTime = 2661
Totaltime = 2678
RightMove: StTime = 2630 EdTime = 1738
FireState: StTime = 1948 EdTime = 2661

91
build.xml Normal file
View File

@@ -0,0 +1,91 @@
<project name="CS8803_P3" default="dist" basedir=".">
<description>
simple example build file
</description>
<!-- set global properties for this build -->
<property name="build" location="classes" />
<property name="dist" location="dist" />
<property name="docs" location="docs" />
<property name="lib" location="lib" />
<property name="res" location="res" />
<property name="project.name" value="CS8803_P3" />
<property name="src" location="src" />
<property name="test" location="test" />
<path id="build.classpath">
<fileset dir="${lib}">
<include name="**/*.jar" />
</fileset>
</path>
<path id="classpath.test">
<path refid="build.classpath" />
<pathelement location="lib/junit-4.10.jar" />
<pathelement location="${build}" />
</path>
<target name="clean" description="clean up">
<!-- Delete the ${build} and ${dist} directory trees -->
<delete dir="${build}" />
<delete dir="${dist}" />
</target>
<target name="compile" depends="copy-resources">
<!-- Compile the java code from ${src} into ${build} -->
<javac srcdir="${src}" destdir="${build}" classpathref="build.classpath" debug="true" source="1.6" target="1.6"/>
</target>
<target name="compile-test" depends="compile">
<javac srcdir="${test}" destdir="${build}" debug="true">
<classpath refid="classpath.test"/>
</javac>
</target>
<target name="copy-resources" depends="init" >
<copy todir="${build}/res">
<fileset dir="${res}">
<include name="**/*" />
</fileset>
</copy>
<copy file="DetailedInfo.txt" todir="${dist}" />
<copy file="player.txt" todir="${dist}" />
</target>
<target name="dist" depends="copy-resources, compile"
description="generate the distribution">
<jar jarfile="${dist}/${project.name}.jar">
<fileset dir="${build}" excludes="**/*Test.class" />
<manifest>
<attribute name="Main-Class" value="dk.itu.mario.engine.Play" />
</manifest>
</jar>
</target>
<!-- Creates Javadoc -->
<target name="docs" depends="compile">
<javadoc packagenames="src" sourcepath="${src}" destdir="${docs}">
<!-- Define which files / directory should get included, we include all -->
<fileset dir="${src}">
<include name="**" />
</fileset>
</javadoc>
</target>
<target name="init">
<!-- Create the time stamp -->
<tstamp />
<!-- Create the build directory structure used by compile -->
<mkdir dir="${build}" />
</target>
<target name="test" depends="compile-test">
<junit haltonfailure="true">
<classpath refid="classpath.test" />
<formatter type="brief" usefile="false" />
<batchtest>
<fileset dir="${build}" includes="**/*Test.class" />
</batchtest>
</junit>
</target>
</project>

BIN
lib/jdom.jar Normal file

Binary file not shown.

BIN
lib/junit-4.10.jar Normal file

Binary file not shown.

BIN
lib/slf4j-api-1.6.4.jar Normal file

Binary file not shown.

BIN
lib/xuggle-xuggler.jar Normal file

Binary file not shown.

BIN
player.txt Normal file

Binary file not shown.

BIN
res/Thumbs.db Normal file

Binary file not shown.

BIN
res/abkey.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

BIN
res/bgsheet.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

BIN
res/endscene.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

BIN
res/enemysheet.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.9 KiB

BIN
res/firemariosheet.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 KiB

BIN
res/font.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

BIN
res/gameovergost.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

BIN
res/itemsheet.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

BIN
res/keys.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

BIN
res/logo.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

BIN
res/mapsheet.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

BIN
res/mariosheet.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

BIN
res/mus/smb3map1.mid Normal file

Binary file not shown.

BIN
res/mus/smb3ovr1.mid Normal file

Binary file not shown.

BIN
res/mus/smb3undr.mid Normal file

Binary file not shown.

BIN
res/mus/smwfortress.mid Normal file

Binary file not shown.

BIN
res/mus/smwovr1.mid Normal file

Binary file not shown.

BIN
res/mus/smwovr2.mid Normal file

Binary file not shown.

BIN
res/mus/smwtitle.mid Normal file

Binary file not shown.

BIN
res/particlesheet.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

BIN
res/racoonmariosheet.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

BIN
res/smallmariosheet.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

BIN
res/snd/1-up.wav Normal file

Binary file not shown.

BIN
res/snd/breakblock.wav Normal file

Binary file not shown.

BIN
res/snd/bump.wav Normal file

Binary file not shown.

BIN
res/snd/cannon.wav Normal file

Binary file not shown.

BIN
res/snd/coin.wav Normal file

Binary file not shown.

BIN
res/snd/death.wav Normal file

Binary file not shown.

BIN
res/snd/exit.wav Normal file

Binary file not shown.

BIN
res/snd/fireball.wav Normal file

Binary file not shown.

BIN
res/snd/jump.wav Normal file

Binary file not shown.

BIN
res/snd/kick.wav Normal file

Binary file not shown.

BIN
res/snd/message.wav Normal file

Binary file not shown.

BIN
res/snd/pipe.wav Normal file

Binary file not shown.

BIN
res/snd/powerdown.wav Normal file

Binary file not shown.

BIN
res/snd/powerup.wav Normal file

Binary file not shown.

BIN
res/snd/sprout.wav Normal file

Binary file not shown.

BIN
res/snd/stagestart.wav Normal file

Binary file not shown.

BIN
res/snd/stomp.wav Normal file

Binary file not shown.

BIN
res/test.lvl Normal file

Binary file not shown.

BIN
res/tiles.dat Normal file

Binary file not shown.

BIN
res/title.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

BIN
res/tweak.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

BIN
res/worldmap.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

BIN
src/dk/itu/.DS_Store vendored Normal file

Binary file not shown.

BIN
src/dk/itu/mario/.DS_Store vendored Normal file

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,10 @@
package dk.itu.mario.MarioInterface;
public interface Constraints {
// the submitted level should has exactly the following information
public static int levelWidth= 320;
public static int gaps = 10;
public static int turtels = 7;
public static int coinBlocks = 10;
}

View File

@@ -0,0 +1,101 @@
package dk.itu.mario.MarioInterface;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
public class GamePlay implements Serializable {
private static final long serialVersionUID = 1L;
public int completionTime; // counts only the current run on the level,
// excluding death games
public int totalTime;// sums all the time, including from previous games if
// player died
public int jumpsNumber; // total number of jumps
public int duckNumber; // total number of ducks
public int timeSpentDucking; // time spent in ducking mode
public int timesPressedRun;// number of times the run key pressed
public int timeSpentRunning; // total time spent running
public int timeRunningRight; // total time spent running to the right
public int timeRunningLeft;// total time spent running to the left
public int emptyBlocksDestroyed; // number of empty blocks destroyed
public int coinsCollected; // number of coins collected
public int coinBlocksDestroyed; // number of coin block destroyed
public int powerBlocksDestroyed; // number of power block destroyed
public int kickedShells; // number of shells Mario kicked
public int enemyKillByFire; // number of enemies killed by shooting them
public int enemyKillByKickingShell; // number of enemies killed by kicking a
// shell on them
public int totalTimeLittleMode; // total time spent in little mode
public int totalTimeLargeMode; // total time spent in large mode
public int totalTimeFireMode; // total time spent in fire mode
public int timesSwichingPower; // number of Times Switched Between Little,
// Large or Fire Mario
public double aimlessJumps; // number of jumps without a reason
public double percentageBlocksDestroyed; // percentage of all blocks
// destroyed
public double percentageCoinBlocksDestroyed; // percentage of coin blocks
// destroyed
public double percentageEmptyBlockesDestroyed; // percentage of empty blocks
// destroyed
public double percentagePowerBlockDestroyed; // percentage of power blocks
// destroyed
public double timesOfDeathByFallingIntoGap; // number of death by falling
// into a gap
public int totalEnemies; // total number of enemies
public int totalEmptyBlocks; // total number of empty blocks
public int totalCoinBlocks; // total number of coin blocks
public int totalpowerBlocks; // total number of power blocks
public int totalCoins; // total number of coins
public int timesOfDeathByRedTurtle; // number of times Mario died by red
// turtle
public int timesOfDeathByGoomba; // number of times Mario died by Goomba
public int timesOfDeathByGreenTurtle; // number of times Mario died by green
// turtle
public int timesOfDeathByArmoredTurtle; // number of times Mario died by
// Armored turtle
public int timesOfDeathByJumpFlower; // number of times Mario died by Jump
// Flower
public int timesOfDeathByCannonBall; // number of time Mario died by Cannon
// Ball
public int timesOfDeathByChompFlower; // number of times Mario died by Chomp
// Flower
public int RedTurtlesKilled; // number of Red Turtle Mario killed
public int GreenTurtlesKilled;// number of Green Turtle Mario killed
public int ArmoredTurtlesKilled; // number of Armored Turtle Mario killed
public int GoombasKilled; // number of Goombas Mario killed
public int CannonBallKilled; // number of Cannon Ball Mario killed
public int JumpFlowersKilled; // number of Jump Flower Mario killed
public int ChompFlowersKilled; // number of Chomp Flower Mario killed
public void write(String fileName) {
ObjectOutputStream out = null;
try {
FileOutputStream fos = new FileOutputStream(fileName);
out = new ObjectOutputStream(fos);
out.writeObject(this);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static GamePlay read(String fileName) {
FileInputStream fis = null;
ObjectInputStream in = null;
GamePlay gp = null;
try {
fis = new FileInputStream(fileName);
in = new ObjectInputStream(fis);
gp = (GamePlay) in.readObject();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return gp;
}
}

View File

@@ -0,0 +1,12 @@
package dk.itu.mario.MarioInterface;
import java.io.File;
public interface LevelGenerator {
//Use one of these methods to generate your level
public LevelInterface generateLevel (GamePlay playerMetrics);
public LevelInterface generateLevel (String detailedInfo);
}

View File

@@ -0,0 +1,41 @@
package dk.itu.mario.MarioInterface;
import dk.itu.mario.engine.sprites.SpriteTemplate;
public interface LevelInterface {
public static byte[] TILE_BEHAVIORS = new byte[256];
public static final int TYPE_OVERGROUND = 0;
public static final int TYPE_UNDERGROUND = 1;
public static final int TYPE_CASTLE = 2;
public static final int BIT_BLOCK_UPPER = 1 << 0;
public static final int BIT_BLOCK_ALL = 1 << 1;
public static final int BIT_BLOCK_LOWER = 1 << 2;
public static final int BIT_SPECIAL = 1 << 3; //mashroom or flower
public static final int BIT_BUMPABLE = 1 << 4;
public static final int BIT_BREAKABLE = 1 << 5;
public static final int BIT_PICKUPABLE = 1 << 6;
public static final int BIT_ANIMATED = 1 << 7;
public void tick();
//Map of WIDTH * HEIGHT that contains the level's design
public byte[][] getMap();
//Map of WIDTH * HEIGHT and contains the placement and type enemies
public SpriteTemplate[][] getSpriteTemplates();
public int getWidth();
public int getHeight();
//These are the place where the level ends
public int getxExit();
public int getyExit();
public String getName();
}

BIN
src/dk/itu/mario/engine/.DS_Store vendored Normal file

Binary file not shown.

View File

@@ -0,0 +1,27 @@
package dk.itu.mario.engine;
public class ArgParser {
public static ParsedArgs parse(String[] cmdLineArgs) {
ParsedArgs parsedArgs = new ParsedArgs();
for (int i = 0; i < cmdLineArgs.length; i++) {
if (cmdLineArgs[i].toUpperCase().startsWith("GENERATOR=")) {
String generatorClass = cmdLineArgs[i].split("=")[1];
parsedArgs.setGeneratorClass(generatorClass);
System.out.println("Generator class set to: " + generatorClass);
} else if (cmdLineArgs[i].toUpperCase().startsWith("SEED=")) {
String levelRandSeed = cmdLineArgs[i].split("=")[1];
if (parsedArgs.setLevelRandSeed(levelRandSeed)) {
System.out.println("Level randomizer seed set to: " + levelRandSeed);
} else {
System.out.println("Unable to parse value of levelRandSeed: "
+ levelRandSeed +". Keeping default value of: "
+ parsedArgs.getLevelRandSeed());
}
} else if (cmdLineArgs[i].toUpperCase().startsWith("VIDEO=")) {
String videoFileName = cmdLineArgs[i].split("=")[1];
parsedArgs.setVideoFileName(videoFileName);
}
}
return parsedArgs;
}
}

View File

@@ -0,0 +1,192 @@
package dk.itu.mario.engine;
import java.awt.AlphaComposite;
import java.awt.Graphics2D;
import java.awt.GraphicsConfiguration;
import java.awt.Image;
import java.awt.Transparency;
import java.awt.image.BufferedImage;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.sound.midi.MidiSystem;
import javax.sound.midi.Sequence;
import javax.sound.midi.Sequencer;
import dk.itu.mario.engine.sonar.SonarSoundEngine;
import dk.itu.mario.engine.sonar.sample.SonarSample;
import java.io.InputStream;
public class Art
{
public static final int SAMPLE_BREAK_BLOCK = 0;
public static final int SAMPLE_GET_COIN = 1;
public static final int SAMPLE_MARIO_JUMP = 2;
public static final int SAMPLE_MARIO_STOMP = 3;
public static final int SAMPLE_MARIO_KICK = 4;
public static final int SAMPLE_MARIO_POWER_UP = 5;
public static final int SAMPLE_MARIO_POWER_DOWN = 6;
public static final int SAMPLE_MARIO_DEATH = 7;
public static final int SAMPLE_ITEM_SPROUT = 8;
public static final int SAMPLE_CANNON_FIRE = 9;
public static final int SAMPLE_SHELL_BUMP = 10;
public static final int SAMPLE_LEVEL_EXIT = 11;
public static final int SAMPLE_MARIO_1UP = 12;
public static final int SAMPLE_MARIO_FIREBALL = 13;
public static Image[][] mario;
public static Image[][] smallMario;
public static Image[][] fireMario;
public static Image[][] enemies;
public static Image[][] items;
public static Image[][] level;
public static Image[][] particles;
public static Image[][] font;
public static Image[][] bg;
public static Image[][] map;
public static Image[][] endScene;
public static Image[][] gameOver;
public static Image logo;
public static Image titleScreen;
public static Image keys, abkey;
public static SonarSample[] samples = new SonarSample[100];
private static Sequence[] songs = new Sequence[10];
private static Sequencer sequencer;
public static boolean mute = false;
private static final String PREFIX="/res";
public static void init(GraphicsConfiguration gc, SonarSoundEngine sound)
{
try
{
mario = cutImage(gc, PREFIX+"/mariosheet.png", 32, 32);
smallMario = cutImage(gc, PREFIX+"/smallmariosheet.png", 16, 16);
fireMario = cutImage(gc, PREFIX+"/firemariosheet.png", 32, 32);
enemies = cutImage(gc, PREFIX+"/enemysheet.png", 16, 32);
items = cutImage(gc,PREFIX+ "/itemsheet.png", 16, 16);
level = cutImage(gc, PREFIX+"/mapsheet.png", 16, 16);
map = cutImage(gc, PREFIX+"/worldmap.png", 16, 16);
particles = cutImage(gc, PREFIX+"/particlesheet.png", 8, 8);
bg = cutImage(gc,PREFIX+ "/bgsheet.png", 32, 32);
logo = getImage(gc, PREFIX+"/logo.gif");
titleScreen = getImage(gc, PREFIX+"/title.gif");
font = cutImage(gc, PREFIX+"/font.gif", 8, 8);
endScene = cutImage(gc,PREFIX+ "/endscene.gif", 96, 96);
gameOver = cutImage(gc, PREFIX+"/gameovergost.gif", 96, 64);
keys = getImage(gc, PREFIX+"/keys.png");
abkey = getImage(gc, PREFIX+"/abkey.png");
if (sound != null)
{
samples[SAMPLE_BREAK_BLOCK] = sound.loadSample(PREFIX+"/snd/breakblock.wav");
samples[SAMPLE_GET_COIN] = sound.loadSample(PREFIX+"/snd/coin.wav");
samples[SAMPLE_MARIO_JUMP] = sound.loadSample(PREFIX+"/snd/jump.wav");
samples[SAMPLE_MARIO_STOMP] = sound.loadSample(PREFIX+"/snd/stomp.wav");
samples[SAMPLE_MARIO_KICK] = sound.loadSample(PREFIX+"/snd/kick.wav");
samples[SAMPLE_MARIO_POWER_UP] = sound.loadSample(PREFIX+"/snd/powerup.wav");
samples[SAMPLE_MARIO_POWER_DOWN] = sound.loadSample(PREFIX+"/snd/powerdown.wav");
samples[SAMPLE_MARIO_DEATH] = sound.loadSample(PREFIX+"/snd/death.wav");
samples[SAMPLE_ITEM_SPROUT] = sound.loadSample(PREFIX+"/snd/sprout.wav");
samples[SAMPLE_CANNON_FIRE] = sound.loadSample(PREFIX+"/snd/cannon.wav");
samples[SAMPLE_SHELL_BUMP] = sound.loadSample(PREFIX+"/snd/bump.wav");
samples[SAMPLE_LEVEL_EXIT] = sound.loadSample(PREFIX+"/snd/exit.wav");
samples[SAMPLE_MARIO_1UP] = sound.loadSample(PREFIX+"/snd/1-up.wav");
samples[SAMPLE_MARIO_FIREBALL] = sound.loadSample(PREFIX+"/snd/fireball.wav");
}
}
catch (Exception e)
{
e.printStackTrace();
}
try
{
sequencer = MidiSystem.getSequencer();
sequencer.open();
songs[0] = MidiSystem.getSequence(Art.class.getResourceAsStream(PREFIX+"/mus/smb3map1.mid"));
songs[1] = MidiSystem.getSequence(Art.class.getResourceAsStream(PREFIX+"/mus/smwovr1.mid"));
songs[2] = MidiSystem.getSequence(Art.class.getResourceAsStream(PREFIX+"/mus/smb3undr.mid"));
songs[3] = MidiSystem.getSequence(Art.class.getResourceAsStream(PREFIX+"/mus/smwfortress.mid"));
songs[4] = MidiSystem.getSequence(Art.class.getResourceAsStream(PREFIX+"/mus/smwtitle.mid"));
}
catch (Exception e)
{
sequencer = null;
e.printStackTrace();
}
}
private static Image getImage(GraphicsConfiguration gc, String imageName) throws IOException
{
InputStream p=Art.class.getResourceAsStream(imageName);
BufferedImage source = ImageIO.read(p);
Image image = gc.createCompatibleImage(source.getWidth(), source.getHeight(), Transparency.BITMASK);
Graphics2D g = (Graphics2D) image.getGraphics();
g.setComposite(AlphaComposite.Src);
g.drawImage(source, 0, 0, null);
g.dispose();
return image;
}
private static Image[][] cutImage(GraphicsConfiguration gc, String imageName, int xSize, int ySize) throws IOException
{
Image source = getImage(gc, imageName);
Image[][] images = new Image[source.getWidth(null) / xSize][source.getHeight(null) / ySize];
for (int x = 0; x < source.getWidth(null) / xSize; x++)
{
for (int y = 0; y < source.getHeight(null) / ySize; y++)
{
Image image = gc.createCompatibleImage(xSize, ySize, Transparency.BITMASK);
Graphics2D g = (Graphics2D) image.getGraphics();
g.setComposite(AlphaComposite.Src);
g.drawImage(source, -x * xSize, -y * ySize, null);
g.dispose();
images[x][y] = image;
}
}
return images;
}
public static void startMusic(int song)
{
if(!mute){
stopMusic();
if (sequencer != null)
{
try
{
sequencer.open();
sequencer.setSequence((Sequence)null);
sequencer.setSequence(songs[song]);
sequencer.setLoopCount(Sequencer.LOOP_CONTINUOUSLY);
sequencer.start();
}
catch (Exception e)
{
}
}
}
}
public static void stopMusic()
{
if (sequencer != null)
{
try
{
sequencer.stop();
sequencer.close();
}
catch (Exception e)
{
}
}
}
}

View File

@@ -0,0 +1,103 @@
package dk.itu.mario.engine;
import java.awt.*;
import java.util.Random;
import dk.itu.mario.level.Level;
public class BgRenderer
{
private int xCam;
private int yCam;
private Image image;
private Graphics2D g;
private static final Color transparent = new Color(0, 0, 0, 0);
private Level level;
private Random random = new Random();
public boolean renderBehaviors = false;
private int width;
private int height;
private int distance;
public BgRenderer(Level level, GraphicsConfiguration graphicsConfiguration, int width, int height, int distance)
{
this.distance = distance;
this.width = width;
this.height = height;
this.level = level;
image = graphicsConfiguration.createCompatibleImage(width, height, Transparency.BITMASK);
g = (Graphics2D) image.getGraphics();
g.setComposite(AlphaComposite.Src);
updateArea(0, 0, width, height);
}
public void setCam(int xCam, int yCam)
{
xCam /= distance;
yCam /= distance;
int xCamD = this.xCam - xCam;
int yCamD = this.yCam - yCam;
this.xCam = xCam;
this.yCam = yCam;
g.setComposite(AlphaComposite.Src);
g.copyArea(0, 0, width, height, xCamD, yCamD);
if (xCamD < 0)
{
if (xCamD < -width) xCamD = -width;
updateArea(width + xCamD, 0, -xCamD, height);
}
else if (xCamD > 0)
{
if (xCamD > width) xCamD = width;
updateArea(0, 0, xCamD, height);
}
if (yCamD < 0)
{
if (yCamD < -width) yCamD = -width;
updateArea(0, height + yCamD, width, -yCamD);
}
else if (yCamD > 0)
{
if (yCamD > width) yCamD = width;
updateArea(0, 0, width, yCamD);
}
}
private void updateArea(int x0, int y0, int w, int h)
{
g.setBackground(transparent);
g.clearRect(x0, y0, w, h);
int xTileStart = (x0 + xCam) / 32;
int yTileStart = (y0 + yCam) / 32;
int xTileEnd = (x0 + xCam + w) / 32;
int yTileEnd = (y0 + yCam + h) / 32;
for (int x = xTileStart; x <= xTileEnd; x++)
{
for (int y = yTileStart; y <= yTileEnd; y++)
{
int b = level.getBlock(x, y) & 0xff;
g.drawImage(Art.bg[b % 8][b / 8], (x << 5) - xCam, (y << 5) - yCam-16, null);
}
}
}
public void render(Graphics g, int tick, float alpha)
{
g.drawImage(image, 0, 0, null);
}
public void setLevel(Level level)
{
this.level = level;
updateArea(0, 0, width, height);
}
}

View File

@@ -0,0 +1,56 @@
package dk.itu.mario.engine;
import dk.itu.mario.level.Level;
import dk.itu.mario.MarioInterface.Constraints;
import dk.itu.mario.engine.sprites.SpriteTemplate;
public final class ConstraintsChecker {
public static boolean check(Level level){
if(level.getWidth() != Constraints.levelWidth)
return false;
//check the number of gaps
int levelGaps = 0, bcoins = 0;
for (int i = 0; i < level.getWidth(); i++) {
if (level.getBlock(i, level.getHeight()) == 0){
levelGaps++;
while (i<level.getWidth() && level.getBlock(i, level.getHeight())==0){
i++;
}
}
}
// if(levelGaps != Constraints.gaps)
// return false;
//check the number of TURTLES
int tur = 0;
for (int i = 0; i < level.getSpriteTemplate().length; i++) {
SpriteTemplate[] st = (SpriteTemplate[])level.getSpriteTemplate()[i];
for (int j = 0; j < st.length; j++) {
if(st[j]!=null){
int t = ((SpriteTemplate)st[j]).type;
if(t== SpriteTemplate.RED_TURTLE || t == SpriteTemplate.GREEN_TURTLE || t == SpriteTemplate.ARMORED_TURTLE)
tur++;
}
}
}
// if(tur != Constraints.turtels)
// return false;
//check the number of coin blocks
for (int i = 0; i < level.getWidth(); i++) {
for (int j = 0; j < level.getHeight(); j++) {
byte block = level.getBlock(i, j);
if ((Level.TILE_BEHAVIORS[block & 0xff] & Level.BIT_BUMPABLE) > 0)
if (! (((Level.TILE_BEHAVIORS[block & 0xff]) & Level.BIT_SPECIAL) > 0))
bcoins++;
}
}
// if(bcoins != Constraints.coinBlocks)
// return false;
return true;
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,26 @@
package dk.itu.mario.engine;
import java.util.*;
import dk.itu.mario.level.Level;
public abstract class LevelFactory {
private static Map<String, Level> levels = new HashMap<String, Level>();
public static void register(String name,Level level){
levels.put(name, level);
}
public static Level retrieve(String name){
return levels.get(name);
}
public static Iterator<String> getKeyset(){
return levels.keySet().iterator();
}
public static Map getLevelsMap(){
return levels;
}
}

View File

@@ -0,0 +1,212 @@
package dk.itu.mario.engine;
import java.awt.*;
import java.util.Random;
import dk.itu.mario.level.Level;
public class LevelRenderer
{
private int xCam;
private int yCam;
private Image image;
private Graphics2D g;
private static final Color transparent = new Color(0, 0, 0, 0);
private Level level;
private Random random = new Random();
public boolean renderBehaviors = false;
public int width;
public int height;
public LevelRenderer(Level level, GraphicsConfiguration graphicsConfiguration, int width, int height)
{
this.width = width;
this.height = height;
this.level = level;
image = graphicsConfiguration.createCompatibleImage(width, height, Transparency.BITMASK);
g = (Graphics2D) image.getGraphics();
g.setComposite(AlphaComposite.Src);
updateArea(0, 0, width, height);
}
public void setCam(int xCam, int yCam)
{
int xCamD = this.xCam - xCam;
int yCamD = this.yCam - yCam;
this.xCam = xCam;
this.yCam = yCam;
g.setComposite(AlphaComposite.Src);
g.copyArea(0, 0, width, height, xCamD, yCamD);
if (xCamD < 0)
{
if (xCamD < -width) xCamD = -width;
updateArea(width + xCamD, 0, -xCamD, height);
}
else if (xCamD > 0)
{
if (xCamD > width) xCamD = width;
updateArea(0, 0, xCamD, height);
}
if (yCamD < 0)
{
if (yCamD < -width) yCamD = -width;
updateArea(0, height + yCamD, width, -yCamD);
}
else if (yCamD > 0)
{
if (yCamD > width) yCamD = width;
updateArea(0, 0, width, yCamD);
}
}
private void updateArea(int x0, int y0, int w, int h)
{
g.setBackground(transparent);
g.clearRect(x0, y0, w, h);
int xTileStart = (x0 + xCam) / 16;
int yTileStart = (y0 + yCam) / 16;
int xTileEnd = (x0 + xCam + w) / 16;
int yTileEnd = (y0 + yCam + h) / 16;
for (int x = xTileStart; x <= xTileEnd; x++)
{
for (int y = yTileStart; y <= yTileEnd; y++)
{
int b = level.getBlock(x, y) & 0xff;
if (((Level.TILE_BEHAVIORS[b]) & Level.BIT_ANIMATED) == 0)
{
g.drawImage(Art.level[b % 16][b / 16], (x << 4) - xCam, (y << 4) - yCam, null);
}
}
}
}
public void render(Graphics g, int tick, float alpha)
{
g.drawImage(image, 0, 0, null);
for (int x = xCam / 16; x <= (xCam + width) / 16; x++)
for (int y = yCam / 16; y <= (yCam + height) / 16; y++)
{
byte b = level.getBlock(x, y);
if (((Level.TILE_BEHAVIORS[b & 0xff]) & Level.BIT_ANIMATED) > 0)
{
int animTime = (tick / 3) % 4;
if ((b % 16) / 4 == 0 && b / 16 == 1)
{
animTime = (tick / 2 + (x + y) / 8) % 20;
if (animTime > 3) animTime = 0;
}
if ((b % 16) / 4 == 3 && b / 16 == 0)
{
animTime = 2;
}
int yo = 0;
// if (x >= 0 && y >= 0 && x < level.getWidth() && y < level.getyHeight()) yo = level.data[x][y];
if (yo > 0) yo = (int) (Math.sin((yo - alpha) / 4.0f * Math.PI) * 8);
g.drawImage(Art.level[(b % 16) / 4 * 4 + animTime][b / 16], (x << 4) - xCam, (y << 4) - yCam - yo, null);
}
/* else if (b == Level.TILE_BONUS)
{
int animTime = (tick / 3) % 4;
int yo = 0;
if (x >= 0 && y >= 0 && x < level.width && y < level.height) yo = level.data[x][y];
if (yo > 0) yo = (int) (Math.sin((yo - alpha) / 4.0f * Math.PI) * 8);
g.drawImage(Art.mapSprites[(4 + animTime)][0], (x << 4) - xCam, (y << 4) - yCam - yo, null);
}*/
if (renderBehaviors)
{
if (((Level.TILE_BEHAVIORS[b & 0xff]) & Level.BIT_BLOCK_UPPER) > 0)
{
g.setColor(Color.RED);
g.fillRect((x << 4) - xCam, (y << 4) - yCam, 16, 2);
}
if (((Level.TILE_BEHAVIORS[b & 0xff]) & Level.BIT_BLOCK_ALL) > 0)
{
g.setColor(Color.RED);
g.fillRect((x << 4) - xCam, (y << 4) - yCam, 16, 2);
g.fillRect((x << 4) - xCam, (y << 4) - yCam + 14, 16, 2);
g.fillRect((x << 4) - xCam, (y << 4) - yCam, 2, 16);
g.fillRect((x << 4) - xCam + 14, (y << 4) - yCam, 2, 16);
}
if (((Level.TILE_BEHAVIORS[b & 0xff]) & Level.BIT_BLOCK_LOWER) > 0)
{
g.setColor(Color.RED);
g.fillRect((x << 4) - xCam, (y << 4) - yCam + 14, 16, 2);
}
if (((Level.TILE_BEHAVIORS[b & 0xff]) & Level.BIT_SPECIAL) > 0)
{
g.setColor(Color.PINK);
g.fillRect((x << 4) - xCam + 2 + 4, (y << 4) - yCam + 2 + 4, 4, 4);
}
if (((Level.TILE_BEHAVIORS[b & 0xff]) & Level.BIT_BUMPABLE) > 0)
{
g.setColor(Color.BLUE);
g.fillRect((x << 4) - xCam + 2, (y << 4) - yCam + 2, 4, 4);
}
if (((Level.TILE_BEHAVIORS[b & 0xff]) & Level.BIT_BREAKABLE) > 0)
{
g.setColor(Color.GREEN);
g.fillRect((x << 4) - xCam + 2 + 4, (y << 4) - yCam + 2, 4, 4);
}
if (((Level.TILE_BEHAVIORS[b & 0xff]) & Level.BIT_PICKUPABLE) > 0)
{
g.setColor(Color.YELLOW);
g.fillRect((x << 4) - xCam + 2, (y << 4) - yCam + 2 + 4, 4, 4);
}
if (((Level.TILE_BEHAVIORS[b & 0xff]) & Level.BIT_ANIMATED) > 0)
{
}
}
}
}
public void repaint(int x, int y, int w, int h)
{
updateArea(x * 16 - xCam, y * 16 - yCam, w * 16, h * 16);
}
public void setLevel(Level level)
{
this.level = level;
updateArea(0, 0, width, height);
}
public void renderExit0(Graphics g, int tick, float alpha, boolean bar)
{
for (int y = level.getyExit() - 8; y < level.getyExit(); y++)
{
g.drawImage(Art.level[12][y == level.getyExit() - 8 ? 4 : 5], (level.getxExit() << 4) - xCam - 16, (y << 4) - yCam, null);
}
int yh = level.getyExit() * 16 - (int) ((Math.sin((tick + alpha) / 20) * 0.5 + 0.5) * 7 * 16) - 8;
if (bar)
{
g.drawImage(Art.level[12][3], (level.getxExit() << 4) - xCam - 16, yh - yCam, null);
g.drawImage(Art.level[13][3], (level.getxExit() << 4) - xCam, yh - yCam, null);
}
}
public void renderExit1(Graphics g, int tick, float alpha)
{
for (int y = level.getyExit() - 8; y < level.getyExit(); y++)
{
g.drawImage(Art.level[13][y == level.getyExit() - 8 ? 4 : 5], (level.getxExit() << 4) - xCam + 16, (y << 4) - yCam, null);
}
}
}

View File

@@ -0,0 +1,306 @@
package dk.itu.mario.engine;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.GraphicsConfiguration;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.image.VolatileImage;
import java.util.Random;
import javax.sound.sampled.LineUnavailableException;
import javax.swing.JComponent;
import dk.itu.mario.MarioInterface.LevelGenerator;
import dk.itu.mario.engine.sonar.FakeSoundEngine;
import dk.itu.mario.engine.sonar.SonarSoundEngine;
import dk.itu.mario.engine.sprites.Mario;
import dk.itu.mario.scene.LevelScene;
import dk.itu.mario.scene.LevelSceneCustom;
import dk.itu.mario.scene.LoseScene;
import dk.itu.mario.scene.Scene;
import dk.itu.mario.scene.WinScene;
public class MarioComponent extends JComponent implements Runnable,
KeyListener, FocusListener, MouseListener {
private static final long serialVersionUID = 739318775993206607L;
public static final int TICKS_PER_SECOND = 24;
public static final int EVOLVE_VERSION = 4;
public static final int GAME_VERSION = 4;
private boolean running = false;
private int width, height;
private GraphicsConfiguration graphicsConfiguration;
private Scene scene;
private SonarSoundEngine sound;
private boolean useScale2x = false;
private boolean isCustom = false;
private LevelGenerator levelGenerator;
private Scale2x scale2x = new Scale2x(320, 240);
public MarioComponent(int width, int height, boolean isCustomized, LevelGenerator levelGenerator) {
addFocusListener(this);
addMouseListener(this);
addKeyListener(this);
this.setFocusable(true);
this.setEnabled(true);
this.width = width;
this.height = height;
this.isCustom = isCustomized;
Dimension size = new Dimension(width, height);
setPreferredSize(size);
setMinimumSize(size);
setMaximumSize(size);
try {
sound = new SonarSoundEngine(64);
} catch (LineUnavailableException e) {
e.printStackTrace();
sound = new FakeSoundEngine();
}
this.setFocusable(true);
this.levelGenerator = levelGenerator;
LevelScene.bothPlayed = false;
}
private void toggleKey(int keyCode, boolean isPressed) {
if (scene == null) {
return;
}
if (keyCode == KeyEvent.VK_LEFT) {
scene.toggleKey(Mario.KEY_LEFT, isPressed);
}
if (keyCode == KeyEvent.VK_RIGHT) {
scene.toggleKey(Mario.KEY_RIGHT, isPressed);
}
if (keyCode == KeyEvent.VK_DOWN) {
scene.toggleKey(Mario.KEY_DOWN, isPressed);
}
if (keyCode == KeyEvent.VK_UP) {
scene.toggleKey(Mario.KEY_UP, isPressed);
}
if (keyCode == KeyEvent.VK_A) {
scene.toggleKey(Mario.KEY_SPEED, isPressed);
}
if (keyCode == KeyEvent.VK_S) {
scene.toggleKey(Mario.KEY_JUMP, isPressed);
}
if (keyCode == KeyEvent.VK_ENTER) {
scene.toggleKey(Mario.KEY_ENTER, isPressed);
}
if (isPressed && keyCode == KeyEvent.VK_F1) {
useScale2x = !useScale2x;
}
if (isPressed && keyCode == KeyEvent.VK_ESCAPE) {
try {
System.exit(1);
} catch (Exception e) {
System.out.println("Unable to exit.");
}
}
}
public void paint(Graphics g) {
super.paint(g);
}
public void update(Graphics g) {
}
public void start() {
if (!running) {
running = true;
new Thread(this, "Game Thread").start();
}
}
public void stop() {
Art.stopMusic();
running = false;
}
public void run() {
graphicsConfiguration = getGraphicsConfiguration();
Art.init(graphicsConfiguration, sound);
VolatileImage image = createVolatileImage(320, 240);
Graphics g = getGraphics();
Graphics og = image.getGraphics();
int lastTick = -1;
long startTime = System.nanoTime();
float time = (System.nanoTime() - startTime) / 1000000000f;
float now = time;
float averagePassedTime = 0;
boolean naiveTiming = true;
///Not sure I understand the weird dichotomy between LevelScene and LevelInterface...
randomLevel = new LevelSceneCustom(graphicsConfiguration, this,
new Random().nextLong(), 0, 0, isCustom, levelGenerator);
Mario.fire = false;
Mario.large = false;
Mario.coins = 0;
Mario.lives = 3;
randomLevel.init();
randomLevel.setSound(sound);
scene = randomLevel;
///
while (running) {
float lastTime = time;
time = (System.nanoTime() - startTime) / 1000000000f;
float passedTime = time - lastTime;
if (passedTime < 0)
naiveTiming = false; // Stop relying on nanotime if it starts
// skipping around in time (ie running
// backwards at least once). This
// sometimes happens on dual core amds.
averagePassedTime = averagePassedTime * 0.9f + passedTime * 0.1f;
if (naiveTiming) {
now = time;
} else {
now += averagePassedTime;
}
int tick = (int) (now * TICKS_PER_SECOND);
if (lastTick == -1)
lastTick = tick;
while (lastTick < tick) {
scene.tick();
lastTick++;
}
float alpha = (float) (now * TICKS_PER_SECOND - tick);
sound.clientTick(alpha);
og.setColor(Color.WHITE);
og.fillRect(0, 0, 320, 240);
scene.render(og, alpha);
if (!this.hasFocus() && tick / 4 % 2 == 0) {
String msg = "CLICK TO PLAY";
drawString(og, msg, 160 - msg.length() * 4 + 1, 110 + 1, 0);
drawString(og, msg, 160 - msg.length() * 4, 110, 7);
}
og.setColor(Color.BLACK);
if (width != 320 || height != 240) {
if (useScale2x) {
g.drawImage(scale2x.scale(image), 0, 0, null);
} else {
g.drawImage(image, 0, 0, 640, 480, null);
}
} else {
g.drawImage(image, 0, 0, null);
}
try {
Thread.sleep(5);
} catch (InterruptedException e) {
}
}
Art.stopMusic();
}
private void drawString(Graphics g, String text, int x, int y, int c) {
char[] ch = text.toCharArray();
for (int i = 0; i < ch.length; i++) {
g.drawImage(Art.font[ch[i] - 32][c], x + i * 8, y, null);
}
}
public void keyPressed(KeyEvent arg0) {
toggleKey(arg0.getKeyCode(), true);
}
public void keyReleased(KeyEvent arg0) {
toggleKey(arg0.getKeyCode(), false);
}
public void keyTyped(KeyEvent arg0) {
}
public void focusGained(FocusEvent arg0) {
}
public void focusLost(FocusEvent arg0) {
}
public void levelWon() {
}
public static final int OPTIMIZED_FIRST = 0;
public static final int MINIMIZED_FIRST = 1;
private LevelScene randomLevel;
public void lose() {
scene = new LoseScene();
scene.setSound(sound);
scene.init();
}
public void win() {
scene = new WinScene();
scene.setSound(sound);
scene.init();
}
public void mouseClicked(MouseEvent e) {
}
public void mouseEntered(MouseEvent e) {
// TODO Auto-generated method stub
}
public void mouseExited(MouseEvent e) {
// TODO Auto-generated method stub
}
public void mousePressed(MouseEvent e) {
// TODO Auto-generated method stub
}
public void mouseReleased(MouseEvent e) {
while (!hasFocus()) {
System.out.println("FORCE IT");
requestFocus();
}
}
/**
* Must return the actual fill of the viewable components
*/
public Dimension getPreferredSize() {
return new Dimension(width, height);
}
}

View File

@@ -0,0 +1,86 @@
package dk.itu.mario.engine;
import dk.itu.mario.MarioInterface.LevelGenerator;
import dk.itu.mario.level.generator.CustomizedLevelGenerator;
import dk.itu.mario.level.generator.MyLevelGenerator;
import dk.itu.mario.level.generator.RandomLevelGenerator;
public class ParsedArgs {
public static final String NO_GEN_ERR = "Generator class not specified (use generator=... argument).";
//Default values per Play class:
private boolean custom = false;
private boolean videoCaptureEnabled = false;
private int levelRandSeed = (int) (Math.random() * Integer.MAX_VALUE);
private String generatorClass = "MyLevel";
private String videoFileName = "LevelGenerator";
public LevelGenerator createLevelGenerator() {
if (generatorClass == null) {
throw new UnsupportedOperationException(NO_GEN_ERR);
}
if ("MyLevel".equals(generatorClass)) {
return new MyLevelGenerator();
} else if ("CustomizedLevel".equalsIgnoreCase(generatorClass)) {
return new CustomizedLevelGenerator();
} else if ("RandomLevel".equalsIgnoreCase(generatorClass)) {
return new RandomLevelGenerator();
} else {
throw new UnsupportedOperationException("Cannot create LevelFactory for unrecognized class:" + generatorClass);
}
}
public String getGeneratorClass() {
return generatorClass;
}
public int getLevelRandSeed() {
return levelRandSeed;
}
public String getVideoFileName() {
return videoFileName;
}
public boolean isCustom() {
return custom;
}
public boolean isGeneratorClassSet() {
return generatorClass != null;
}
public boolean isVideoCaptureEnabled() {
return videoCaptureEnabled;
}
public void setGeneratorClass(String generatorClass) {
if (generatorClass == null) {
throw new UnsupportedOperationException(NO_GEN_ERR);
}
this.generatorClass = generatorClass;
if ("MyLevel".equals(generatorClass)) {
custom = true;
} else if ("CustomizedLevel".equalsIgnoreCase(generatorClass)) {
custom = true;
} else {
custom = false;
}
}
public void setVideoFileName(String videoFileName) {
this.videoFileName = videoFileName;
this.videoCaptureEnabled = true;
}
public boolean setLevelRandSeed(String randSeedString) {
try {
levelRandSeed = Integer.valueOf(randSeedString);
return true;
} catch (NumberFormatException nfe) {
return false;
}
}
}

View File

@@ -0,0 +1,30 @@
package dk.itu.mario.engine;
import java.awt.Dimension;
import java.awt.Toolkit;
import javax.swing.JFrame;
public class Play {
public static void main(String[] args) {
JFrame frame = new JFrame("Mario Experience Showcase");
ParsedArgs parsedArgs = ArgParser.parse(args);
MarioComponent mario = new MarioComponent(640, 480, parsedArgs.isCustom(), parsedArgs.createLevelGenerator());
frame.setContentPane(mario);
frame.setResizable(false);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
frame.setLocation((screenSize.width - frame.getWidth()) / 2,
(screenSize.height - frame.getHeight()) / 2);
frame.setVisible(true);
mario.start();
}
}

View File

@@ -0,0 +1,130 @@
/**
* Scale2x.java
*
* Written by Markus Persson of Mojang Specifications for a super mario programming contest.
* Implements the Scale2x algorithm described here: http://scale2x.sourceforge.net/algorithm.html
* Works on any input image size, and uses a fancy border hack to prevent range checking.
* It's fast enough for real time use on smaller images (320x240 and thereabouts)
*
* This code is public domain. Do whatever you want with it.
*/
package dk.itu.mario.engine;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferInt;
public class Scale2x
{
private int width;
private int height;
private BufferedImage sourceImage;
private int[] sourcePixels;
private Graphics sourceGraphics;
private BufferedImage targetImage;
private int[] targetPixels;
/**
* Creates a new Scale2x object. The new object will scale images of the specified size to images
* that are twice as large.<br>
*
* @param width The width of the images to be scaled
* @param height The height of the images to be scaled
*/
public Scale2x(int width, int height)
{
this.width = width;
this.height = height;
// A border of one pixel in each direction, and one down, to avoid if statements in the scale loop
sourceImage = new BufferedImage(width + 2, height + 3, BufferedImage.TYPE_INT_RGB);
DataBufferInt sourceDataBuffer = (DataBufferInt) sourceImage.getRaster().getDataBuffer();
sourcePixels = sourceDataBuffer.getData();
sourceGraphics = sourceImage.getGraphics();
targetImage = new BufferedImage(width * 2, height * 2, BufferedImage.TYPE_INT_RGB);
DataBufferInt targetDataBuffer = (DataBufferInt) targetImage.getRaster().getDataBuffer();
targetPixels = targetDataBuffer.getData();
}
/**
* Scales an image and returns a twice as large image.<br>
* This assumes the input image is of the dimensions specified in the Scale2x constructor.<br>
* The returned image is a reference to the internal scale target in this Scale2x, so it
* will get changed if you call this method again, so don't hold on to it for too long.<br>
* In other words:<br>
* <code>Image i0 = scale2x.scale(image0);<br>
* Image i1 = scale2x.scale(image1);<br>
* if (i0 == i1) System.exit(0); // Will always terminate</code><br>
*
* @param img The image to be scaled
* @returns A scaled image. If you want that image to survive the next call to this method, make a copy of it.
*/
public Image scale(Image img)
{
// Offset the image by one pixel so there's a border around it.
// This lets us avoid having to check that A-I are in range of the image before samping them
sourceGraphics.drawImage(img, 1, 1, null);
int line = width + 2;
for (int y = 0; y < height; y++)
{
// Two lines of target pixel pointers
int tp0 = y * width * 4 - 1;
int tp1 = tp0 + width * 2;
// Three lines of source pixel pointers
int sp0 = (y) * line;
int sp1 = (y + 1) * line;
int sp2 = (y + 2) * line;
// Fill the initial A-I values
int A = sourcePixels[sp0];
int B = sourcePixels[++sp0];
int C = sourcePixels[++sp0];
int D = sourcePixels[sp1];
int E = sourcePixels[++sp1];
int F = sourcePixels[++sp1];
int G = sourcePixels[sp2];
int H = sourcePixels[++sp2];
int I = sourcePixels[++sp2];
for (int x = 0; x < width; x++)
{
if (B != H && D != F)
{
targetPixels[++tp0] = D == B ? D : E;
targetPixels[++tp0] = B == F ? F : E;
targetPixels[++tp1] = D == H ? D : E;
targetPixels[++tp1] = H == F ? F : E;
}
else
{
targetPixels[++tp0] = E;
targetPixels[++tp0] = E;
targetPixels[++tp1] = E;
targetPixels[++tp1] = E;
}
// Scroll A-I left
A = B;
B = C;
D = E;
E = F;
G = H;
H = I;
// Resample rightmost edge
C = sourcePixels[++sp0];
F = sourcePixels[++sp1];
I = sourcePixels[++sp2];
}
}
return targetImage;
}
}

BIN
src/dk/itu/mario/engine/sonar/.DS_Store vendored Normal file

Binary file not shown.

View File

@@ -0,0 +1,38 @@
package dk.itu.mario.engine.sonar;
import dk.itu.mario.engine.sonar.sample.SonarSample;
public class FakeSoundEngine extends SonarSoundEngine
{
public void setListener(SoundListener soundListener)
{
}
public void shutDown()
{
}
public SonarSample loadSample(String resourceName)
{
return null;
}
public void play(SonarSample sample, SoundSource soundSource, float volume, float priority, float rate)
{
}
public void clientTick(float alpha)
{
}
public void tick()
{
}
public void run()
{
}
}

View File

@@ -0,0 +1,33 @@
package dk.itu.mario.engine.sonar;
/**
* @author Administrator
*/
public class FixedSoundSource implements SoundSource
{
private float x;
private float y;
public FixedSoundSource(float x, float y)
{
this.x = x;
this.y = y;
}
public FixedSoundSource(SoundSource soundSource)
{
this.x = soundSource.getX(1);
this.y = soundSource.getY(1);
}
public float getX(float alpha)
{
return x;
}
public float getY(float alpha)
{
return y;
}
}

View File

@@ -0,0 +1,145 @@
package dk.itu.mario.engine.sonar;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import javax.sound.sampled.*;
import dk.itu.mario.engine.sonar.mixer.ListenerMixer;
import dk.itu.mario.engine.sonar.sample.SamplePlayer;
import dk.itu.mario.engine.sonar.sample.SonarSample;
import dk.itu.mario.engine.sonar.sample.SampleLoader;
public class SonarSoundEngine implements Runnable
{
private SonarSample silentSample;
private SourceDataLine sdl;
private int rate = 44100;
private ListenerMixer listenerMixer;
private int bufferSize = rate / 100; // 10 ms
private ByteBuffer soundBuffer = ByteBuffer.allocate(bufferSize * 4);
private float[] leftBuf, rightBuf;
private float amplitude = 1;
private float targetAmplitude = 1;
private boolean alive = true;
protected SonarSoundEngine()
{
}
public SonarSoundEngine(int maxChannels) throws LineUnavailableException
{
silentSample = new SonarSample(new float[] {0}, 44100);
Mixer mixer = AudioSystem.getMixer(null);
sdl = (SourceDataLine) mixer.getLine(new Line.Info(SourceDataLine.class));
sdl.open(new AudioFormat(rate, 16, 2, true, false), bufferSize * 2 * 2 * 2 * 2 * 2);
soundBuffer.order(ByteOrder.LITTLE_ENDIAN);
sdl.start();
try
{
/* FloatControl volumeControl = (FloatControl) sdl.getControl(FloatControl.Type.MASTER_GAIN);
volumeControl.setValue(volumeControl.getMaximum());*/
}
catch (IllegalArgumentException e)
{
System.out.println("Failed to set the sound volume");
}
listenerMixer = new ListenerMixer(maxChannels);
leftBuf = new float[bufferSize];
rightBuf = new float[bufferSize];
Thread thread = new Thread(this);
thread.setDaemon(true);
thread.setPriority(10);
thread.start();
}
public void setListener(SoundListener soundListener)
{
listenerMixer.setSoundListener(soundListener);
}
public void shutDown()
{
alive = false;
}
public SonarSample loadSample(String resourceName)
{
try
{
return SampleLoader.loadSample(resourceName);
}
catch (Exception e)
{
System.out.println("Failed to load sample " + resourceName + ". Using silent sample");
e.printStackTrace();
return silentSample;
}
}
public void play(SonarSample sample, SoundSource soundSource, float volume, float priority, float rate)
{
synchronized (listenerMixer)
{
if(!dk.itu.mario.engine.Art.mute)
listenerMixer.addSoundProducer(new SamplePlayer((SonarSample) sample, rate), soundSource, volume, priority);
}
}
public void clientTick(float alpha)
{
synchronized (listenerMixer)
{
listenerMixer.update(alpha);
}
}
public void tick()
{
soundBuffer.clear();
// targetAmplitude = (targetAmplitude - 1) * 0.9f + 1;
// targetAmplitude = (targetAmplitude - 1) * 0.9f + 1;
synchronized (listenerMixer)
{
float maxAmplitude = listenerMixer.read(leftBuf, rightBuf, rate);
// if (maxAmplitude > targetAmplitude) targetAmplitude = maxAmplitude;
}
soundBuffer.clear();
float gain = 32000;
for (int i = 0; i < bufferSize; i++)
{
// amplitude += (targetAmplitude - amplitude) / rate;
// amplitude = 1;
// float gain = 30000;
int l = (int) (leftBuf[i] * gain);
int r = (int) (rightBuf[i] * gain);
if (l > 32767) l = 32767;
if (r > 32767) r = 32767;
if (l < -32767) l = -32767;
if (r < -32767) r = -32767;
soundBuffer.putShort((short)l);
soundBuffer.putShort((short)r);
}
sdl.write(soundBuffer.array(), 0, bufferSize * 2 * 2);
}
public void run()
{
while (alive)
{
tick();
}
}
}

View File

@@ -0,0 +1,6 @@
package dk.itu.mario.engine.sonar;
public interface SoundListener extends SoundSource
{
}

View File

@@ -0,0 +1,8 @@
package dk.itu.mario.engine.sonar;
public interface SoundProducer
{
public float read(float[] buf, int readRate);
public void skip(int samplesToSkip, int readRate);
public boolean isLive();
}

View File

@@ -0,0 +1,7 @@
package dk.itu.mario.engine.sonar;
public interface SoundSource
{
public float getX(float alpha);
public float getY(float alpha);
}

View File

@@ -0,0 +1,7 @@
package dk.itu.mario.engine.sonar;
public interface StereoSoundProducer
{
public float read(float[] leftBuf, float[] rightBuf, int readRate);
public void skip(int samplesToSkip, int readRate);
}

Binary file not shown.

View File

@@ -0,0 +1,93 @@
package dk.itu.mario.engine.sonar.mixer;
import java.util.*;
import dk.itu.mario.engine.sonar.SoundListener;
import dk.itu.mario.engine.sonar.SoundProducer;
import dk.itu.mario.engine.sonar.SoundSource;
import dk.itu.mario.engine.sonar.StereoSoundProducer;
public class ListenerMixer implements StereoSoundProducer
{
private List<Sound> sounds = new ArrayList<Sound>();
private float[] buf = new float[0];
private int maxChannels;
private SoundListener soundListener;
public ListenerMixer(int maxChannels)
{
this.maxChannels = maxChannels;
}
public void setSoundListener(SoundListener soundListener)
{
this.soundListener = soundListener;
}
public void addSoundProducer(SoundProducer producer, SoundSource soundSource, float volume, float priority)
{
sounds.add(new Sound(producer, soundSource, volume, priority));
}
public void update(float alpha)
{
for (Iterator it = sounds.iterator(); it.hasNext();)
{
Sound sound = (Sound) it.next();
sound.update(soundListener, alpha);
if (!sound.isLive())
{
it.remove();
}
}
}
@SuppressWarnings("unchecked")
public float read(float[] leftBuf, float[] rightBuf, int readRate)
{
if (buf.length != leftBuf.length) buf = new float[leftBuf.length];
if (sounds.size() > maxChannels)
{
Collections.sort(sounds);
}
Arrays.fill(leftBuf, 0);
Arrays.fill(rightBuf, 0);
float maxAmplitude = 0;
for (int i = 0; i < sounds.size(); i++)
{
Sound sound = (Sound) sounds.get(i);
if (i < maxChannels)
{
sound.read(buf, readRate);
float rp = (sound.pan<0?1:1-sound.pan)*sound.amplitude;
float lp = (sound.pan>0?1:1+sound.pan)*sound.amplitude;
for (int j = 0; j < leftBuf.length; j++)
{
leftBuf[j] += buf[j]*lp;
rightBuf[j] += buf[j]*rp;
if (leftBuf[j]>maxAmplitude) maxAmplitude = leftBuf[j];
if (rightBuf[j]>maxAmplitude) maxAmplitude = rightBuf[j];
}
}
else
{
sound.skip(leftBuf.length, readRate);
}
}
return maxAmplitude;
}
public void skip(int samplesToSkip, int readRate)
{
for (int i = 0; i < sounds.size(); i++)
{
Sound sound = (Sound) sounds.get(i);
sound.skip(samplesToSkip, readRate);
}
}
}

View File

@@ -0,0 +1,84 @@
package dk.itu.mario.engine.sonar.mixer;
import dk.itu.mario.engine.sonar.SoundListener;
import dk.itu.mario.engine.sonar.SoundProducer;
import dk.itu.mario.engine.sonar.SoundSource;
public class Sound implements Comparable
{
private static final double l10 = Math.log(10);
private SoundProducer producer;
private SoundSource source;
private float volume;
private float priority;
private float x, y, z;
private float score = 0;
public float pan;
public float amplitude;
public Sound(SoundProducer producer, SoundSource source, float volume, float priority)
{
this.producer = producer;
this.source = source;
this.volume = volume;
this.priority = priority;
}
public void update(SoundListener listener, float alpha)
{
x = source.getX(alpha)-listener.getX(alpha);
y = source.getY(alpha)-listener.getY(alpha);
float distSqr = x*x+y*y+z*z;
float dist = (float)Math.sqrt(distSqr);
float REFERENCE_DISTANCE = 1;
float ROLLOFF_FACTOR = 2;
// float dB = (float)(volume + (20 * (Math.log(1.0 / distSqr) / l10)));
float dB = (float)(volume - 20*Math.log(1 + ROLLOFF_FACTOR*(dist-REFERENCE_DISTANCE)/REFERENCE_DISTANCE )/ l10);
dB = Math.min(dB, +6);
// dB = Math.max(dB, MIN_GAIN);
score = dB*priority;
// double angle = WMath.atan2(y, x);
float p = -x/320.0f;
if (p<-1) p = -1;
if (p>1) p = 1;
float dd = distSqr/16;
if (dd>1) dd = 1;
pan =(p*dd);
amplitude = volume*1f;
}
public void read(float[] buf, int readRate)
{
producer.read(buf, readRate);
}
public void skip(int samplesToSkip, int readRate)
{
producer.skip(samplesToSkip, readRate);
}
public boolean isLive()
{
return producer.isLive();
}
public int compareTo(Object o)
{
Sound s = (Sound)o;
if (s.score>score) return 1;
if (s.score<score) return -1;
return 0;
}
}

Binary file not shown.

View File

@@ -0,0 +1,114 @@
package dk.itu.mario.engine.sonar.sample;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.UnsupportedAudioFileException;
public class SampleLoader
{
/**
* Loads a sample from an url
*/
public static SonarSample loadSample(String resourceName) throws UnsupportedAudioFileException, IOException
{
// Hack to prevent "mark/reset not supported" on some systems
InputStream in=SampleLoader.class.getResourceAsStream(resourceName);
byte[] d = rip(in);
AudioInputStream ais = AudioSystem.getAudioInputStream(new ByteArrayInputStream(d));
return buildSample(rip(ais), ais.getFormat());
}
/**
* Rips the entire contents of an inputstream into a byte array
*/
private static byte[] rip(InputStream in) throws IOException
{
ByteArrayOutputStream bos = new ByteArrayOutputStream();
byte[] b = new byte[4096];
int read = 0;
while ((read = in.read(b)) > 0)
{
bos.write(b, 0, read);
}
bos.close();
return bos.toByteArray();
}
/**
* Reorganizes audio sample data into the intenal sonar format
*/
private static SonarSample buildSample(byte[] b, AudioFormat af) throws UnsupportedAudioFileException
{
// Rip audioformat data
int channels = af.getChannels();
int sampleSize = af.getSampleSizeInBits();
float rate = af.getFrameRate();
boolean signed = af.getEncoding() == AudioFormat.Encoding.PCM_SIGNED;
// Sanity checking
if (channels != 1) throw new UnsupportedAudioFileException("Only mono samples are supported");
if (!(sampleSize == 8 || sampleSize == 16 || sampleSize == 32)) throw new UnsupportedAudioFileException("Unsupported sample size");
if (!(af.getEncoding() == AudioFormat.Encoding.PCM_UNSIGNED || af.getEncoding() == AudioFormat.Encoding.PCM_SIGNED)) throw new UnsupportedAudioFileException("Unsupported encoding");
// Wrap the data into a bytebuffer, and set up the byte order
ByteBuffer bb = ByteBuffer.wrap(b);
bb.order(af.isBigEndian() ? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN);
int s = b.length / (sampleSize / 8);
float[] buf = new float[s];
// Six different cases for reordering the data. Can this be improved without slowing it down?
if (sampleSize == 8)
{
if (signed)
{
for (int i = 0; i < s; i++)
buf[i] = bb.get() / (float)0x80;
}
else
{
for (int i = 0; i < s; i++)
buf[i] = ((bb.get()&0xFF)-0x80) / (float)0x80;
}
}
else if (sampleSize == 16)
{
if (signed)
{
for (int i = 0; i < s; i++)
buf[i] = bb.getShort() / (float)0x8000;
}
else
{
for (int i = 0; i < s; i++)
buf[i] = ((bb.getShort()&0xFFFF)-0x8000) / (float)0x8000;
}
}
else if (sampleSize == 32)
{
if (signed)
{
for (int i = 0; i < s; i++)
buf[i] = bb.getInt() / (float)0x80000000;
}
else
{
// Nasty.. check this.
for (int i = 0; i < s; i++)
buf[i] = ((bb.getInt()&0xFFFFFFFFl)-0x80000000l) / (float)0x80000000;
}
}
// Return the completed sample
return new SonarSample(buf, rate);
}
}

View File

@@ -0,0 +1,57 @@
package dk.itu.mario.engine.sonar.sample;
import dk.itu.mario.engine.sonar.SoundProducer;
public class SamplePlayer implements SoundProducer
{
private SonarSample sample;
private float pos = 0;
public boolean alive = true;
private float rate;
public SamplePlayer(SonarSample sample, float rate)
{
this.rate = rate;
this.sample = sample;
}
public float read(float[] buf, int readRate)
{
float step = (sample.rate*rate)/readRate;
for (int i=0; i<buf.length; i++)
{
if (pos>=sample.buf.length)
{
buf[i] = 0;
alive = false;
}
else
{
buf[i]=sample.buf[(int)(pos)];
}
pos+=step;
}
return 1;
}
public void skip(int samplesToSkip, int readRate)
{
float step = sample.rate/readRate;
pos+=step*samplesToSkip;
if (pos>=sample.buf.length)
{
alive = false;
}
}
public boolean isLive()
{
return alive;
}
}

View File

@@ -0,0 +1,13 @@
package dk.itu.mario.engine.sonar.sample;
public class SonarSample
{
public final float[] buf;
public final float rate;
public SonarSample(float[] buf, float rate)
{
this.buf = buf;
this.rate = rate;
}
}

Binary file not shown.

View File

@@ -0,0 +1,152 @@
package dk.itu.mario.engine.sprites;
import dk.itu.mario.engine.Art;
import dk.itu.mario.scene.LevelScene;
public class BulletBill extends Sprite
{
private int width = 4;
int height = 24;
private LevelScene world;
public int facing;
public boolean avoidCliffs = false;
public int anim;
public boolean dead = false;
private int deadTime = 0;
public BulletBill(LevelScene world, float x, float y, int dir)
{
sheet = Art.enemies;
this.x = x;
this.y = y;
this.world = world;
xPicO = 8;
yPicO = 31;
height = 12;
facing = 0;
wPic = 16;
yPic = 5;
xPic = 0;
ya = -5;
this.facing = dir;
}
public void collideCheck()
{
if (dead) return;
float xMarioD = world.mario.x - x;
float yMarioD = world.mario.y - y;
float w = 16;
if (xMarioD > -16 && xMarioD < 16)
{
if (yMarioD > -height && yMarioD < world.mario.height)
{
if (world.mario.ya > 0 && yMarioD <= 0 && (!world.mario.onGround || !world.mario.wasOnGround))
{
world.mario.stomp(this);
dead = true;
xa = 0;
ya = 1;
deadTime = 100;
}
else
{
world.mario.getHurt(this);
}
}
}
}
public void move()
{
if (deadTime > 0)
{
deadTime--;
if (deadTime == 0)
{
deadTime = 1;
for (int i = 0; i < 8; i++)
{
world.addSprite(new Sparkle((int) (x + Math.random() * 16 - 8) + 4, (int) (y - Math.random() * 8) + 4, (float) (Math.random() * 2 - 1), (float) Math.random() * -1, 0, 1, 5));
}
spriteContext.removeSprite(this);
}
x += xa;
y += ya;
ya *= 0.95;
ya += 1;
return;
}
float sideWaysSpeed = 4f;
xa = facing * sideWaysSpeed;
xFlipPic = facing == -1;
move(xa, 0);
}
private boolean move(float xa, float ya)
{
x += xa;
return true;
}
public boolean fireballCollideCheck(Fireball fireball)
{
if (deadTime != 0) return false;
float xD = fireball.x - x;
float yD = fireball.y - y;
if (xD > -16 && xD < 16)
{
if (yD > -height && yD < fireball.height)
{
return true;
}
}
return false;
}
public boolean shellCollideCheck(Shell shell)
{
if (deadTime != 0) return false;
float xD = shell.x - x;
float yD = shell.y - y;
if (xD > -16 && xD < 16)
{
if (yD > -height && yD < shell.height)
{
world.sound.play(Art.samples[Art.SAMPLE_MARIO_KICK], this, 1, 1, 1);
dead = true;
xa = 0;
ya = 1;
deadTime = 100;
if(world.recorder != null)
world.recorder.shellKillRecord(this);
return true;
}
}
return false;
}
}

View File

@@ -0,0 +1,41 @@
package dk.itu.mario.engine.sprites;
import dk.itu.mario.engine.Art;
import dk.itu.mario.level.Level;
public class CoinAnim extends Sprite
{
private int life = 10;
public CoinAnim(int xTile, int yTile)
{
sheet = Art.level;
wPic = hPic = 16;
x = xTile * 16;
y = yTile * 16 - 16;
xa = 0;
ya = -6f;
xPic = 0;
yPic = 2;
}
public void move()
{
if (life-- < 0)
{
Sprite.spriteContext.removeSprite(this);
for (int xx = 0; xx < 2; xx++)
for (int yy = 0; yy < 2; yy++)
Sprite.spriteContext.addSprite(new Sparkle((int)x + xx * 8 + (int) (Math.random() * 8), (int)y + yy * 8 + (int) (Math.random() * 8), 0, 0, 0, 2, 5));
}
xPic = life & 3;
x += xa;
y += ya;
ya += 1;
}
}

View File

@@ -0,0 +1,443 @@
package dk.itu.mario.engine.sprites;
import java.awt.Graphics;
import dk.itu.mario.engine.Art;
import dk.itu.mario.level.Level;
import dk.itu.mario.scene.LevelScene;
public class Enemy extends Sprite
{
public static final int ENEMY_RED_KOOPA = 0;
public static final int ENEMY_GREEN_KOOPA = 1;
public static final int ENEMY_GOOMBA = 2;
public static final int ENEMY_SPIKY = 3;
public static final int ENEMY_FLOWER = 4;
private static float GROUND_INERTIA = 0.89f;
private static float AIR_INERTIA = 0.89f;
private float runTime;
private boolean onGround = false;
private boolean mayJump = false;
private int jumpTime = 0;
private float xJumpSpeed;
private float yJumpSpeed;
int width = 4;
int height = 24;
private LevelScene world;
public int facing;
public int deadTime = 0;
public boolean flyDeath = false;
public boolean avoidCliffs = true;
public int type;
public boolean winged = true;
private int wingTime = 0;
public boolean noFireballDeath;
public Enemy(LevelScene world, int x, int y, int dir, int type, boolean winged)
{
this.type = type;
sheet = Art.enemies;
this.winged = winged;
this.world = world;
this.x = x;
this.y = y;
xPicO = 8;
yPicO = 31;
avoidCliffs = type == Enemy.ENEMY_RED_KOOPA;
noFireballDeath = type == Enemy.ENEMY_SPIKY;
yPic = type;
if (yPic > 1) height = 12;
facing = dir;
if (facing == 0) facing = 1;
this.wPic = 16;
}
public void collideCheck()
{
if (deadTime != 0)
{
return;
}
float xMarioD = world.mario.x - x;
float yMarioD = world.mario.y - y;
float w = 16;
//if the distance to mario is within the sprite (in x)
if (xMarioD > -width*2-4 && xMarioD < width*2+4)
{
//if the distance to mario is within the sprite (in y)
if (yMarioD > -height && yMarioD < world.mario.height)
{
if (type != Enemy.ENEMY_SPIKY && world.mario.ya > 0 && yMarioD <= 0 && (!world.mario.onGround || !world.mario.wasOnGround))
{
world.mario.stomp(this);
if (winged)
{
winged = false;
ya = 0;
}
else
{
this.yPicO = 31 - (32 - 8);
hPic = 8;
if (spriteTemplate != null) spriteTemplate.isDead = true;
deadTime = 10;
winged = false;
if (type == Enemy.ENEMY_RED_KOOPA)
{
spriteContext.addSprite(new Shell(world, x, y, 0));
}
else if (type == Enemy.ENEMY_GREEN_KOOPA)
{
spriteContext.addSprite(new Shell(world, x, y, 1));
}
}
}
else
{
world.mario.getHurt(this);
}
}
}
}
public void move()
{
//TODO: some kind of suicide error when one enemy is created
if (y > world.level.getHeight() * 16 + 16 && deadTime <= 0)
{
if(world.recorder != null)
world.recorder.killSuicideRecord(this);
deadTime = 1;
}
wingTime++;
if (deadTime > 0)
{
deadTime--;
if (deadTime == 0)
{
deadTime = 1;
for (int i = 0; i < 8; i++)
{
world.addSprite(new Sparkle((int) (x + Math.random() * 16 - 8) + 4, (int) (y - Math.random() * 8) + 4, (float) (Math.random() * 2 - 1), (float) Math.random() * -1, 0, 1, 5));
}
spriteContext.removeSprite(this);
}
if (flyDeath)
{
x += xa;
y += ya;
ya *= 0.95;
ya += 1;
}
return;
}
float sideWaysSpeed = 1.75f;
// float sideWaysSpeed = onGround ? 2.5f : 1.2f;
if (xa > 2)
{
facing = 1;
}
if (xa < -2)
{
facing = -1;
}
xa = facing * sideWaysSpeed;
mayJump = (onGround);
xFlipPic = facing == -1;
runTime += (Math.abs(xa)) + 5;
int runFrame = ((int) (runTime / 20)) % 2;
if (!onGround)
{
runFrame = 1;
}
if (!move(xa, 0)) facing = -facing;
onGround = false;
move(0, ya);
ya *= winged ? 0.95f : 0.85f;
if (onGround)
{
xa *= GROUND_INERTIA;
}
else
{
xa *= AIR_INERTIA;
}
if (!onGround)
{
if (winged)
{
ya += 0.6f;
}
else
{
ya += 2;
}
}
else if (winged)
{
ya = -10;
}
if (winged) runFrame = wingTime / 4 % 2;
xPic = runFrame;
}
private boolean move(float xa, float ya)
{
while (xa > 8)
{
if (!move(8, 0)) return false;
xa -= 8;
}
while (xa < -8)
{
if (!move(-8, 0)) return false;
xa += 8;
}
while (ya > 8)
{
if (!move(0, 8)) return false;
ya -= 8;
}
while (ya < -8)
{
if (!move(0, -8)) return false;
ya += 8;
}
boolean collide = false;
if (ya > 0)
{
if (isBlocking(x + xa - width, y + ya, xa, 0)) collide = true;
else if (isBlocking(x + xa + width, y + ya, xa, 0)) collide = true;
else if (isBlocking(x + xa - width, y + ya + 1, xa, ya)) collide = true;
else if (isBlocking(x + xa + width, y + ya + 1, xa, ya)) collide = true;
}
if (ya < 0)
{
if (isBlocking(x + xa, y + ya - height, xa, ya)) collide = true;
else if (collide || isBlocking(x + xa - width, y + ya - height, xa, ya)) collide = true;
else if (collide || isBlocking(x + xa + width, y + ya - height, xa, ya)) collide = true;
}
if (xa > 0)
{
if (isBlocking(x + xa + width, y + ya - height, xa, ya)) collide = true;
if (isBlocking(x + xa + width, y + ya - height / 2, xa, ya)) collide = true;
if (isBlocking(x + xa + width, y + ya, xa, ya)) collide = true;
if (avoidCliffs && onGround && !world.level.isBlocking((int) ((x + xa + width) / 16), (int) ((y) / 16 + 1), xa, 1)) collide = true;
}
if (xa < 0)
{
if (isBlocking(x + xa - width, y + ya - height, xa, ya)) collide = true;
if (isBlocking(x + xa - width, y + ya - height / 2, xa, ya)) collide = true;
if (isBlocking(x + xa - width, y + ya, xa, ya)) collide = true;
if (avoidCliffs && onGround && !world.level.isBlocking((int) ((x + xa - width) / 16), (int) ((y) / 16 + 1), xa, 1)) collide = true;
}
if (collide)
{
if (xa < 0)
{
x = (int) ((x - width) / 16) * 16 + width;
this.xa = 0;
}
if (xa > 0)
{
x = (int) ((x + width) / 16 + 1) * 16 - width - 1;
this.xa = 0;
}
if (ya < 0)
{
y = (int) ((y - height) / 16) * 16 + height;
jumpTime = 0;
this.ya = 0;
}
if (ya > 0)
{
y = (int) (y / 16 + 1) * 16 - 1;
onGround = true;
}
return false;
}
else
{
x += xa;
y += ya;
return true;
}
}
private boolean isBlocking(float _x, float _y, float xa, float ya)
{
int x = (int) (_x / 16);
int y = (int) (_y / 16);
if (x == (int) (this.x / 16) && y == (int) (this.y / 16)) return false;
boolean blocking = world.level.isBlocking(x, y, xa, ya);
byte block = world.level.getBlock(x, y);
return blocking;
}
public boolean shellCollideCheck(Shell shell)
{
if (deadTime != 0) return false;
float xD = shell.x - x;
float yD = shell.y - y;
if (xD > -16 && xD < 16)
{
if (yD > -height && yD < shell.height)
{
world.sound.play(Art.samples[Art.SAMPLE_MARIO_KICK], this, 1, 1, 1);
xa = shell.facing * 2;
ya = -5;
flyDeath = true;
if (spriteTemplate != null) spriteTemplate.isDead = true;
deadTime = 100;
winged = false;
hPic = -hPic;
yPicO = -yPicO + 16;
if(world.recorder != null)
world.recorder.shellKillRecord(this);
return true;
}
}
return false;
}
public boolean fireballCollideCheck(Fireball fireball)
{
if (deadTime != 0) return false;
float xD = fireball.x - x;
float yD = fireball.y - y;
if (xD > -16 && xD < 16)
{
if (yD > -height && yD < fireball.height)
{
if (noFireballDeath) return true;
world.sound.play(Art.samples[Art.SAMPLE_MARIO_KICK], this, 1, 1, 1);
xa = fireball.facing * 2;
ya = -5;
flyDeath = true;
if (spriteTemplate != null) spriteTemplate.isDead = true;
deadTime = 100;
winged = false;
hPic = -hPic;
yPicO = -yPicO + 16;
if(world.recorder != null)
world.recorder.fireKillRecord(this);
return true;
}
}
return false;
}
public void bumpCheck(int xTile, int yTile)
{
if (deadTime != 0) return;
if (x + width > xTile * 16 && x - width < xTile * 16 + 16 && yTile == (int) ((y - 1) / 16))
{
world.sound.play(Art.samples[Art.SAMPLE_MARIO_KICK], this, 1, 1, 1);
xa = -world.mario.facing * 2;
ya = -5;
flyDeath = true;
if (spriteTemplate != null) spriteTemplate.isDead = true;
deadTime = 100;
winged = false;
hPic = -hPic;
yPicO = -yPicO + 16;
}
}
public void render(Graphics og, float alpha)
{
if (winged)
{
int xPixel = (int) (xOld + (x - xOld) * alpha) - xPicO;
int yPixel = (int) (yOld + (y - yOld) * alpha) - yPicO;
if (type == Enemy.ENEMY_GREEN_KOOPA || type == Enemy.ENEMY_RED_KOOPA)
{
}
else
{
xFlipPic = !xFlipPic;
og.drawImage(sheet[wingTime / 4 % 2][4], xPixel + (xFlipPic ? wPic : 0) + (xFlipPic ? 10 : -10), yPixel + (yFlipPic ? hPic : 0) - 8, xFlipPic ? -wPic : wPic, yFlipPic ? -hPic : hPic, null);
xFlipPic = !xFlipPic;
}
}
super.render(og, alpha);
if (winged)
{
int xPixel = (int) (xOld + (x - xOld) * alpha) - xPicO;
int yPixel = (int) (yOld + (y - yOld) * alpha) - yPicO;
if (type == Enemy.ENEMY_GREEN_KOOPA || type == Enemy.ENEMY_RED_KOOPA)
{
og.drawImage(sheet[wingTime / 4 % 2][4], xPixel + (xFlipPic ? wPic : 0) + (xFlipPic ? 10 : -10), yPixel + (yFlipPic ? hPic : 0) - 10, xFlipPic ? -wPic : wPic, yFlipPic ? -hPic : hPic, null);
}
else
{
og.drawImage(sheet[wingTime / 4 % 2][4], xPixel + (xFlipPic ? wPic : 0) + (xFlipPic ? 10 : -10), yPixel + (yFlipPic ? hPic : 0) - 8, xFlipPic ? -wPic : wPic, yFlipPic ? -hPic : hPic, null);
}
}
}
}

View File

@@ -0,0 +1,63 @@
package dk.itu.mario.engine.sprites;
import dk.itu.mario.engine.Art;
import dk.itu.mario.scene.LevelScene;
public class FireFlower extends Sprite
{
private int width = 4;
int height = 24;
private LevelScene world;
public int facing;
public boolean avoidCliffs = false;
private int life;
public FireFlower(LevelScene world, int x, int y)
{
sheet = Art.items;
this.x = x;
this.y = y;
this.world = world;
xPicO = 8;
yPicO = 15;
xPic = 1;
yPic = 0;
height = 12;
facing = 1;
wPic = hPic = 16;
life = 0;
}
public void collideCheck()
{
float xMarioD = world.mario.x - x;
float yMarioD = world.mario.y - y;
float w = 16;
if (xMarioD > -16 && xMarioD < 16)
{
if (yMarioD > -height && yMarioD < world.mario.height)
{
world.mario.getFlower();
spriteContext.removeSprite(this);
}
}
}
public void move()
{
if (life<9)
{
layer = 0;
y--;
life++;
return;
}
}
}

View File

@@ -0,0 +1,220 @@
package dk.itu.mario.engine.sprites;
import dk.itu.mario.engine.Art;
import dk.itu.mario.scene.LevelScene;
public class Fireball extends Sprite
{
private static float GROUND_INERTIA = 0.89f;
private static float AIR_INERTIA = 0.89f;
private float runTime;
private boolean onGround = false;
private int width = 4;
int height = 24;
private LevelScene world;
public int facing;
public boolean avoidCliffs = false;
public int anim;
public boolean dead = false;
private int deadTime = 0;
public Fireball(LevelScene world, float x, float y, int facing)
{
sheet = Art.particles;
this.x = x;
this.y = y;
this.world = world;
xPicO = 4;
yPicO = 4;
yPic = 3;
height = 8;
this.facing = facing;
wPic = 8;
hPic = 8;
xPic = 4;
ya = 4;
}
public void move()
{
if (deadTime > 0)
{
for (int i = 0; i < 8; i++)
{
world.addSprite(new Sparkle((int) (x + Math.random() * 8 - 4)+4, (int) (y + Math.random() * 8-4)+2, (float) Math.random() * 2 - 1-facing, (float) Math.random() *2 -1, 0, 1, 5));
}
spriteContext.removeSprite(this);
return;
}
if (facing != 0) anim++;
float sideWaysSpeed = 8f;
// float sideWaysSpeed = onGround ? 2.5f : 1.2f;
if (xa > 2)
{
facing = 1;
}
if (xa < -2)
{
facing = -1;
}
xa = facing * sideWaysSpeed;
world.checkFireballCollide(this);
xFlipPic = facing == -1;
runTime += (Math.abs(xa)) + 5;
xPic = (anim) % 4;
if (!move(xa, 0))
{
die();
}
onGround = false;
move(0, ya);
if (onGround) ya = -10;
ya *= 0.95f;
if (onGround)
{
xa *= GROUND_INERTIA;
}
else
{
xa *= AIR_INERTIA;
}
if (!onGround)
{
ya += 1.5;
}
}
private boolean move(float xa, float ya)
{
while (xa > 8)
{
if (!move(8, 0)) return false;
xa -= 8;
}
while (xa < -8)
{
if (!move(-8, 0)) return false;
xa += 8;
}
while (ya > 8)
{
if (!move(0, 8)) return false;
ya -= 8;
}
while (ya < -8)
{
if (!move(0, -8)) return false;
ya += 8;
}
boolean collide = false;
if (ya > 0)
{
if (isBlocking(x + xa - width, y + ya, xa, 0)) collide = true;
else if (isBlocking(x + xa + width, y + ya, xa, 0)) collide = true;
else if (isBlocking(x + xa - width, y + ya + 1, xa, ya)) collide = true;
else if (isBlocking(x + xa + width, y + ya + 1, xa, ya)) collide = true;
}
if (ya < 0)
{
if (isBlocking(x + xa, y + ya - height, xa, ya)) collide = true;
else if (collide || isBlocking(x + xa - width, y + ya - height, xa, ya)) collide = true;
else if (collide || isBlocking(x + xa + width, y + ya - height, xa, ya)) collide = true;
}
if (xa > 0)
{
if (isBlocking(x + xa + width, y + ya - height, xa, ya)) collide = true;
if (isBlocking(x + xa + width, y + ya - height / 2, xa, ya)) collide = true;
if (isBlocking(x + xa + width, y + ya, xa, ya)) collide = true;
if (avoidCliffs && onGround && !world.level.isBlocking((int) ((x + xa + width) / 16), (int) ((y) / 16 + 1), xa, 1)) collide = true;
}
if (xa < 0)
{
if (isBlocking(x + xa - width, y + ya - height, xa, ya)) collide = true;
if (isBlocking(x + xa - width, y + ya - height / 2, xa, ya)) collide = true;
if (isBlocking(x + xa - width, y + ya, xa, ya)) collide = true;
if (avoidCliffs && onGround && !world.level.isBlocking((int) ((x + xa - width) / 16), (int) ((y) / 16 + 1), xa, 1)) collide = true;
}
if (collide)
{
if (xa < 0)
{
x = (int) ((x - width) / 16) * 16 + width;
this.xa = 0;
}
if (xa > 0)
{
x = (int) ((x + width) / 16 + 1) * 16 - width - 1;
this.xa = 0;
}
if (ya < 0)
{
y = (int) ((y - height) / 16) * 16 + height;
this.ya = 0;
}
if (ya > 0)
{
y = (int) (y / 16 + 1) * 16 - 1;
onGround = true;
}
return false;
}
else
{
x += xa;
y += ya;
return true;
}
}
private boolean isBlocking(float _x, float _y, float xa, float ya)
{
int x = (int) (_x / 16);
int y = (int) (_y / 16);
if (x == (int) (this.x / 16) && y == (int) (this.y / 16)) return false;
boolean blocking = world.level.isBlocking(x, y, xa, ya);
byte block = world.level.getBlock(x, y);
return blocking;
}
public void die()
{
dead = true;
xa = -facing * 2;
ya = -5;
deadTime = 100;
}
}

View File

@@ -0,0 +1,103 @@
package dk.itu.mario.engine.sprites;
import dk.itu.mario.level.Level;
import dk.itu.mario.scene.LevelScene;
import dk.itu.mario.engine.sprites.*;
public class FlowerEnemy extends Enemy
{
private int tick;
private int yStart;
private int jumpTime = 0;
private LevelScene world;
public FlowerEnemy(LevelScene world, int x, int y)
{
super(world, x, y, 1, ENEMY_SPIKY, false);
noFireballDeath = false;
this.world = world;
this.xPic = 0;
this.yPic = 6;
this.yPicO = 24;
this.height = 12;
this.width = 2;
yStart = y;
ya = -8;
this.y-=1;
this.layer = 0;
for (int i=0; i<4; i++)
{
move();
}
}
public void move()
{
if (deadTime > 0)
{
deadTime--;
if (deadTime == 0)
{
deadTime = 1;
for (int i = 0; i < 8; i++)
{
world.addSprite(new Sparkle((int) (x + Math.random() * 16 - 8) + 4, (int) (y - Math.random() * 8) + 4, (float) (Math.random() * 2 - 1), (float) Math.random() * -1, 0, 1, 5));
}
spriteContext.removeSprite(this);
}
x += xa;
y += ya;
ya *= 0.95;
ya += 1;
return;
}
tick++;
if (y>=yStart)
{
y = yStart;
int xd = (int)(Math.abs(world.mario.x-x));
jumpTime++;
if (jumpTime>40 && xd>24)
{
ya = -8;
}
else
{
ya = 0;
}
}
else
{
jumpTime = 0;
}
y+=ya;
ya*=0.9;
ya+=0.1f;
xPic = ((tick/2)&1)*2+((tick/6)&1);
}
/* public void render(Graphics og, float alpha)
{
if (!visible) return;
int xPixel = (int)(xOld+(x-xOld)*alpha)-xPicO;
int yPixel = (int)(yOld+(y-yOld)*alpha)-yPicO;
int a = ((tick/3)&1)*2;
// a += ((tick/8)&1);
og.drawImage(sheet[a*2+0][6], xPixel-8, yPixel+8, 16, 32, null);
og.drawImage(sheet[a*2+1][6], xPixel+8, yPixel+8, 16, 32, null);
}*/
}

View File

@@ -0,0 +1,918 @@
package dk.itu.mario.engine.sprites;
import dk.itu.mario.engine.Art;
import dk.itu.mario.engine.DataRecorder;
import dk.itu.mario.engine.sonar.FixedSoundSource;
import dk.itu.mario.level.Level;
import dk.itu.mario.scene.LevelScene;
import dk.itu.mario.scene.Scene;
public class Mario extends Sprite
{
public static boolean large = false;
public static boolean fire = false;
public static int coins = 0;
public static int lives = 3;
public static String levelString = "none";
public static void resetStatic()
{
large = false;
fire = false;
coins = 0;
lives = 3;
levelString = "none";
}
public static final int KEY_LEFT = 0;
public static final int KEY_RIGHT = 1;
public static final int KEY_DOWN = 2;
public static final int KEY_UP = 3;
public static final int KEY_JUMP = 4;
public static final int KEY_SPEED = 5;
public static final int KEY_ENTER = 6;
private static float GROUND_INERTIA = 0.89f;
private static float AIR_INERTIA = 0.89f;
public boolean[] keys;
private float runTime;
boolean wasOnGround = false;
boolean onGround = false;
private boolean mayJump = false;
public boolean ducking = false;
public boolean running = false;
public int direction = 0;
private boolean sliding = false;
private int jumpTime = 0;
private float xJumpSpeed;
private float yJumpSpeed;
private boolean canShoot = false;
int width = 4;
int height = 24;
private LevelScene world;
public int facing;
private int powerUpTime = 0;
public int xDeathPos, yDeathPos;
public int deathTime = 0;
public int winTime = 0;
private int invulnerableTime = 0;
public Sprite carried = null;
private static Mario instance;
public Mario(LevelScene world)
{
Mario.instance = this;
this.world = world;
keys = Scene.keys;
x = 32;
y = 0;
facing = 1;
//TODO: REMOVE THESE TEST VARIABLES
// Mario.large = true;
// Mario.fire = true;
setLarge(Mario.large, Mario.fire);
}
private boolean lastLarge;
private boolean lastFire;
private boolean newLarge;
private boolean newFire;
private void blink(boolean on)
{
Mario.large = on?newLarge:lastLarge;
Mario.fire = on?newFire:lastFire;
if (large)
{
sheet = Art.mario;
if (fire)
sheet = Art.fireMario;
xPicO = 16;
yPicO = 31;
wPic = hPic = 32;
}
else
{
sheet = Art.smallMario;
xPicO = 8;
yPicO = 15;
wPic = hPic = 16;
}
calcPic();
}
void setLarge(boolean large, boolean fire)
{
if (fire) large = true;
if (!large) fire = false;
lastLarge = Mario.large;
lastFire = Mario.fire;
Mario.large = large;
Mario.fire = fire;
newLarge = Mario.large;
newFire = Mario.fire;
blink(true);
}
public void move()
{
if(deathTime == 0 && winTime == 0){
if (keys[KEY_DOWN] && large && ducking)
{
if(world.recorder != null && world.recorder.recording)
world.recorder.startDuckRecord();
}
else
{
if(world.recorder != null && world.recorder.recording && !ducking)
world.recorder.endDuckRecord();
}
}
if(deathTime == 0 && winTime == 0){
if(keys[KEY_SPEED]){
if(world.recorder!= null && world.recorder.recording){
world.recorder.startRunningRecord();
}
running = true;
}
else{
if(world.recorder!= null && world.recorder.recording){
world.recorder.endRunningRecord();
}
running = false;
}
}
if (winTime > 0)
{
winTime++;
xa = 0;
ya = 0;
return;
}
if (deathTime > 0)
{
deathTime++;
if (deathTime < 11)
{
xa = 0;
ya = 0;
}
else if (deathTime == 11)
{
ya = -15;
}
else
{
ya += 2;
}
x += xa;
y += ya;
return;
}
if (powerUpTime != 0)
{
if (powerUpTime > 0)
{
powerUpTime--;
blink(((powerUpTime / 3) & 1) == 0);
}
else
{
powerUpTime++;
blink(((-powerUpTime / 3) & 1) == 0);
}
if (powerUpTime == 0) world.paused = false;
calcPic();
return;
}
if (invulnerableTime > 0) invulnerableTime--;
visible = ((invulnerableTime / 2) & 1) == 0;
wasOnGround = onGround;
float sideWaysSpeed = keys[KEY_SPEED] ? 1.2f : 0.6f;
// float sideWaysSpeed = onGround ? 2.5f : 1.2f;
if (onGround)
{
if (keys[KEY_DOWN] && large)
{
if(world.recorder != null)
world.recorder.startDuckRecord();
ducking = true;
}
else
{
if(world.recorder != null)
world.recorder.endDuckRecord();
ducking = false;
}
if(world.recorder != null)
world.recorder.recordJumpLand();
}
if (xa > 2)
{
facing = 1;
}
if (xa < -2)
{
facing = -1;
}
if (keys[KEY_JUMP] || (jumpTime < 0 && !onGround && !sliding))
{
if (jumpTime < 0)
{
xa = xJumpSpeed;
ya = -jumpTime * yJumpSpeed;
jumpTime++;
}
else if (onGround && mayJump)
{
world.sound.play(Art.samples[Art.SAMPLE_MARIO_JUMP], this, 1, 1, 1);
xJumpSpeed = 0;
yJumpSpeed = -1.9f;
jumpTime = 7;
ya = jumpTime * yJumpSpeed;
onGround = false;
sliding = false;
if(world.recorder != null){
world.recorder.isInAir = true;
world.recorder.recordJump();
}
}
else if (sliding && mayJump)
{
world.sound.play(Art.samples[Art.SAMPLE_MARIO_JUMP], this, 1, 1, 1);
xJumpSpeed = -facing * 6.0f;
yJumpSpeed = -2.0f;
jumpTime = -6;
xa = xJumpSpeed;
ya = -jumpTime * yJumpSpeed;
onGround = false;
sliding = false;
facing = -facing;
}
else if (jumpTime > 0)
{
xa += xJumpSpeed;
ya = jumpTime * yJumpSpeed;
jumpTime--;
}
}
else
{
jumpTime = 0;
}
if(world.mario.xa > 0){
if(direction != 1){
direction = 1;
if(world.recorder != null){
// world.recorder.switchRecord();
world.recorder.startRightMoveRecord();
}
}
}
else if(world.mario.xa < 0){
if(direction != -1){
direction = -1;
if(world.recorder != null){
// world.recorder.switchRecord();
world.recorder.startLeftMoveRecord();
}
}
}
else{
//was moving right
if(direction == 1 && world.recorder!= null){
world.recorder.endRightMoveRecord();
}
//was moving left
else if(direction == -1 && world.recorder!= null){
world.recorder.endLeftMoveRecord();
}
direction = 0;
}
if (keys[KEY_LEFT] && !ducking)
{
if (facing == 1) sliding = false;
xa -= sideWaysSpeed;
if (jumpTime >= 0) facing = -1;
}
if (keys[KEY_RIGHT] && !ducking)
{
if (facing == -1) sliding = false;
xa += sideWaysSpeed;
if (jumpTime >= 0) facing = 1;
}
if ((!keys[KEY_LEFT] && !keys[KEY_RIGHT]) || ducking || ya < 0 || onGround)
{
sliding = false;
}
if (keys[KEY_SPEED] && canShoot && Mario.fire && world.fireballsOnScreen<2)
{
world.sound.play(Art.samples[Art.SAMPLE_MARIO_FIREBALL], this, 1, 1, 1);
world.addSprite(new Fireball(world, x+facing*6, y-20, facing));
}
canShoot = !keys[KEY_SPEED];
mayJump = (onGround || sliding) && !keys[KEY_JUMP];
xFlipPic = facing == -1;
runTime += (Math.abs(xa)) + 5;
if (Math.abs(xa) < 0.5f)
{
runTime = 0;
xa = 0;
}
calcPic();
if (sliding)
{
for (int i = 0; i < 1; i++)
{
world.addSprite(new Sparkle((int) (x + Math.random() * 4 - 2) + facing * 8, (int) (y + Math.random() * 4) - 24, (float) (Math.random() * 2 - 1), (float) Math.random() * 1, 0, 1, 5));
}
ya *= 0.5f;
}
onGround = false;
move(xa, 0);
move(0, ya);
if (y > world.level.getHeight() * 16 + 16)
{
dieJump();
}
if (x < 0)
{
x = 0;
xa = 0;
}
// if(x > world.level.xExit * 16 && ! world.level.flipped || x < world.level.xExit * 16 && world.level.flipped )
if(x > world.level.getxExit() * 16 )
{
win();
}
if (x > world.level.getWidth() * 16)
{
x = world.level.getWidth() * 16;
xa = 0;
}
ya *= 0.85f;
if (onGround)
{
xa *= GROUND_INERTIA;
}
else
{
xa *= AIR_INERTIA;
}
if (!onGround)
{
ya += 3;
}
if (carried != null)
{
carried.x = x + facing * 8;
carried.y = y - 2;
if (!keys[KEY_SPEED])
{
carried.release(this);
carried = null;
if(world.recorder != null){
world.recorder.shellUnleashedRecord();
}
}
}
}
private void calcPic()
{
int runFrame = 0;
if (large)
{
runFrame = ((int) (runTime / 20)) % 4;
if (runFrame == 3) runFrame = 1;
if (carried == null && Math.abs(xa) > 10) runFrame += 3;
if (carried != null) runFrame += 10;
if (!onGround)
{
if (carried != null) runFrame = 12;
else if (Math.abs(xa) > 10) runFrame = 7;
else runFrame = 6;
}
}
else
{
runFrame = ((int) (runTime / 20)) % 2;
if (carried == null && Math.abs(xa) > 10) runFrame += 2;
if (carried != null) runFrame += 8;
if (!onGround)
{
if (carried != null) runFrame = 9;
else if (Math.abs(xa) > 10) runFrame = 5;
else runFrame = 4;
}
}
if (onGround && ((facing == -1 && xa > 0) || (facing == 1 && xa < 0)))
{
if (xa > 1 || xa < -1) runFrame = large ? 9 : 7;
if (xa > 3 || xa < -3)
{
for (int i = 0; i < 3; i++)
{
world.addSprite(new Sparkle((int) (x + Math.random() * 8 - 4), (int) (y + Math.random() * 4), (float) (Math.random() * 2 - 1), (float) Math.random() * -1, 0, 1, 5));
}
}
}
if (large)
{
if (ducking) runFrame = 14;
height = ducking ? 12 : 24;
}
else
{
height = 12;
}
xPic = runFrame;
}
private boolean move(float xa, float ya)
{
while (xa > 8)
{
if (!move(8, 0)) return false;
xa -= 8;
}
while (xa < -8)
{
if (!move(-8, 0)) return false;
xa += 8;
}
while (ya > 8)
{
if (!move(0, 8)) return false;
ya -= 8;
}
while (ya < -8)
{
if (!move(0, -8)) return false;
ya += 8;
}
boolean collide = false;
if (ya > 0)
{
if (isBlocking(x + xa - width, y + ya, xa, 0)) collide = true;
else if (isBlocking(x + xa + width, y + ya, xa, 0)) collide = true;
else if (isBlocking(x + xa - width, y + ya + 1, xa, ya)) collide = true;
else if (isBlocking(x + xa + width, y + ya + 1, xa, ya)) collide = true;
}
if (ya < 0)
{
if (isBlocking(x + xa, y + ya - height, xa, ya)) collide = true;
else if (collide || isBlocking(x + xa - width, y + ya - height, xa, ya)) collide = true;
else if (collide || isBlocking(x + xa + width, y + ya - height, xa, ya)) collide = true;
}
if (xa > 0)
{
sliding = true;
if (isBlocking(x + xa + width, y + ya - height, xa, ya)) collide = true;
else sliding = false;
if (isBlocking(x + xa + width, y + ya - height / 2, xa, ya)) collide = true;
else sliding = false;
if (isBlocking(x + xa + width, y + ya, xa, ya)) collide = true;
else sliding = false;
}
if (xa < 0)
{
sliding = true;
if (isBlocking(x + xa - width, y + ya - height, xa, ya)) collide = true;
else sliding = false;
if (isBlocking(x + xa - width, y + ya - height / 2, xa, ya)) collide = true;
else sliding = false;
if (isBlocking(x + xa - width, y + ya, xa, ya)) collide = true;
else sliding = false;
}
if (collide)
{
if (xa < 0)
{
x = (int) ((x - width) / 16) * 16 + width;
this.xa = 0;
}
if (xa > 0)
{
x = (int) ((x + width) / 16 + 1) * 16 - width - 1;
this.xa = 0;
}
if (ya < 0)
{
y = (int) ((y - height) / 16) * 16 + height;
jumpTime = 0;
this.ya = 0;
}
if (ya > 0)
{
y = (int) ((y - 1) / 16 + 1) * 16 - 1;
onGround = true;
}
return false;
}
else
{
x += xa;
y += ya;
return true;
}
}
private boolean isBlocking(float _x, float _y, float xa, float ya)
{
//translate into block mode (since blocks are 16x16)
int x = (int) (_x / 16);
int y = (int) (_y / 16);
if (x==(int)(this.x/16) && y==(int)(this.y/16))
return false;
boolean blocking = world.level.isBlocking(x, y, xa, ya);
byte block = world.level.getBlock(x, y);
if (((Level.TILE_BEHAVIORS[block & 0xff]) & Level.BIT_PICKUPABLE) > 0)
{
if(world.recorder != null)
world.recorder.recordCoin();
Mario.getCoin();
world.sound.play(Art.samples[Art.SAMPLE_GET_COIN], new FixedSoundSource(x * 16 + 8, y * 16 + 8), 1, 1, 1);
world.level.setBlock(x, y, (byte) 0);
for (int xx = 0; xx < 2; xx++)
for (int yy = 0; yy < 2; yy++)
world.addSprite(new Sparkle(x * 16 + xx * 8 + (int) (Math.random() * 8), y * 16 + yy * 8 + (int) (Math.random() * 8), 0, 0, 0, 2, 5));
}
if (blocking && ya < 0)
{
world.bump(x, y, large);
}
return blocking;
}
public void stomp(Enemy enemy)
{
if (deathTime > 0 || world.paused) return;
float targetY = enemy.y - enemy.height / 2;
move(0, targetY - y);
world.sound.play(Art.samples[Art.SAMPLE_MARIO_KICK], this, 1, 1, 1);
xJumpSpeed = 0;
yJumpSpeed = -1.9f;
jumpTime = 8;
ya = jumpTime * yJumpSpeed;
onGround = false;
sliding = false;
invulnerableTime = 1;
if(world.recorder!=null)
world.recorder.killStompRecord(enemy);
}
public void stomp(Shell shell)
{
if (deathTime > 0 || world.paused) return;
if (keys[KEY_SPEED] && shell.facing == 0)
{
carried = shell;
shell.carried = true;
}
else
{
float targetY = shell.y - shell.height / 2;
move(0, targetY - y);
world.sound.play(Art.samples[Art.SAMPLE_MARIO_KICK], this, 1, 1, 1);
xJumpSpeed = 0;
yJumpSpeed = -1.9f;
jumpTime = 8;
ya = jumpTime * yJumpSpeed;
onGround = false;
sliding = false;
invulnerableTime = 1;
if(shell.xa == 0 && world.recorder!= null){
world.recorder.shellUnleashedRecord();
}
}
}
public void getHurt(Sprite sprite)
{
if (deathTime > 0 || world.paused) return;
if (invulnerableTime > 0) return;
if (large)
{
world.paused = true;
powerUpTime = -3 * 6;
world.sound.play(Art.samples[Art.SAMPLE_MARIO_POWER_DOWN], this, 1, 1, 1);
if (fire)
{
world.mario.setLarge(true, false);
if(world.recorder != null){
world.recorder.endFireRecord();
world.recorder.startLargeRecord();
}
}
else
{
world.mario.setLarge(false, false);
if(world.recorder != null){
world.recorder.endLargeRecord();
world.recorder.startLittleRecord();
}
}
invulnerableTime = 32;
}
else
{
dieSprite(sprite);
}
}
private void win()
{
xDeathPos = (int) x;
yDeathPos = (int) y;
world.paused = true;
winTime = 1;
Art.stopMusic();
world.sound.play(Art.samples[Art.SAMPLE_LEVEL_EXIT], this, 1, 1, 1);
}
public void dieSprite(Sprite sprite){
die();
if(world.recorder != null){
world.recorder.dieRecord(sprite);
}
}
public void dieTime(){
die();
if(world.recorder!=null){
world.recorder.dieTimeRecord();
}
}
public void dieJump(){
die();
if(world.recorder!=null){
world.recorder.dieJumpRecord();
}
}
public void die()
{
xDeathPos = (int) x;
yDeathPos = (int) y;
world.paused = true;
deathTime = 1;
Art.stopMusic();
world.sound.play(Art.samples[Art.SAMPLE_MARIO_DEATH], this, 1, 1, 1);
if(world.recorder != null){
if(running)
world.recorder.endRunningRecord();
if(large && !fire){
world.recorder.endLargeRecord();
}
if(fire){
world.recorder.endFireRecord();
}
if(!large && !fire)
world.recorder.endLittleRecord();
if(ducking)
world.recorder.endDuckRecord();
world.recorder.endTime();
world.recorder.recordJumpLand();
}
large = false;
fire = false;
}
public void getFlower()
{
if (deathTime > 0 || world.paused) return;
if (!fire)
{
world.paused = true;
powerUpTime = 3 * 6;
world.sound.play(Art.samples[Art.SAMPLE_MARIO_POWER_UP], this, 1, 1, 1);
world.mario.setLarge(true, true);
if(world.recorder != null){
if(large){
world.recorder.endLargeRecord();
}
else{
world.recorder.endLittleRecord();
}
world.recorder.startFireRecord();
}
}
else
{
Mario.getCoin();
world.sound.play(Art.samples[Art.SAMPLE_GET_COIN], this, 1, 1, 1);
}
}
public void getMushroom()
{
if (deathTime > 0 || world.paused) return;
if (!large)
{
world.paused = true;
powerUpTime = 3 * 6;
world.sound.play(Art.samples[Art.SAMPLE_MARIO_POWER_UP], this, 1, 1, 1);
world.mario.setLarge(true, false);
if(world.recorder != null){
world.recorder.endLittleRecord();
world.recorder.startLargeRecord();
}
}
else
{
Mario.getCoin();
world.sound.play(Art.samples[Art.SAMPLE_GET_COIN], this, 1, 1, 1);
}
}
public void kick(Shell shell)
{
if (deathTime > 0 || world.paused) return;
if (keys[KEY_SPEED])
{
carried = shell;
shell.carried = true;
}
else
{
world.sound.play(Art.samples[Art.SAMPLE_MARIO_KICK], this, 1, 1, 1);
invulnerableTime = 1;
if(world.recorder!=null)
world.recorder.shellUnleashedRecord();
}
}
public void stomp(BulletBill bill)
{
if (deathTime > 0 || world.paused) return;
float targetY = bill.y - bill.height / 2;
move(0, targetY - y);
world.sound.play(Art.samples[Art.SAMPLE_MARIO_KICK], this, 1, 1, 1);
xJumpSpeed = 0;
yJumpSpeed = -1.9f;
jumpTime = 8;
ya = jumpTime * yJumpSpeed;
onGround = false;
sliding = false;
invulnerableTime = 1;
if(world.recorder!=null)
world.recorder.killStompRecord(bill);
}
public byte getKeyMask()
{
int mask = 0;
for (int i = 0; i < 7; i++)
{
if (keys[i]) mask |= (1 << i);
}
return (byte) mask;
}
public void setKeys(byte mask)
{
for (int i = 0; i < 7; i++)
{
keys[i] = (mask & (1 << i)) > 0;
}
}
public static void get1Up()
{
instance.world.sound.play(Art.samples[Art.SAMPLE_MARIO_1UP], instance, 1, 1, 1);
lives++;
if (lives==99)
{
lives = 99;
}
}
public static void getCoin()
{
coins++;
if (coins==100)
{
coins = 0;
get1Up();
}
}
}

View File

@@ -0,0 +1,223 @@
package dk.itu.mario.engine.sprites;
import dk.itu.mario.engine.Art;
import dk.itu.mario.scene.LevelScene;
public class Mushroom extends Sprite
{
private static float GROUND_INERTIA = 0.89f;
private static float AIR_INERTIA = 0.89f;
private float runTime;
private boolean onGround = false;
private boolean mayJump = false;
private int jumpTime = 0;
private float xJumpSpeed;
private float yJumpSpeed;
private int width = 4;
int height = 24;
private LevelScene world;
public int facing;
public boolean avoidCliffs = false;
private int life;
public Mushroom(LevelScene world, int x, int y)
{
sheet = Art.items;
this.x = x;
this.y = y;
this.world = world;
xPicO = 8;
yPicO = 15;
yPic = 0;
height = 12;
facing = 1;
wPic = hPic = 16;
life = 0;
}
public void collideCheck()
{
float xMarioD = world.mario.x - x;
float yMarioD = world.mario.y - y;
float w = 16;
if (xMarioD > -16 && xMarioD < 16)
{
if (yMarioD > -height && yMarioD < world.mario.height)
{
world.mario.getMushroom();
spriteContext.removeSprite(this);
}
}
}
public void move()
{
if (life<9)
{
layer = 0;
y--;
life++;
return;
}
float sideWaysSpeed = 1.75f;
layer = 1;
// float sideWaysSpeed = onGround ? 2.5f : 1.2f;
if (xa > 2)
{
facing = 1;
}
if (xa < -2)
{
facing = -1;
}
xa = facing * sideWaysSpeed;
mayJump = (onGround);
xFlipPic = facing == -1;
runTime += (Math.abs(xa)) + 5;
if (!move(xa, 0)) facing = -facing;
onGround = false;
move(0, ya);
ya *= 0.85f;
if (onGround)
{
xa *= GROUND_INERTIA;
}
else
{
xa *= AIR_INERTIA;
}
if (!onGround)
{
ya += 2;
}
}
private boolean move(float xa, float ya)
{
while (xa > 8)
{
if (!move(8, 0)) return false;
xa -= 8;
}
while (xa < -8)
{
if (!move(-8, 0)) return false;
xa += 8;
}
while (ya > 8)
{
if (!move(0, 8)) return false;
ya -= 8;
}
while (ya < -8)
{
if (!move(0, -8)) return false;
ya += 8;
}
boolean collide = false;
if (ya > 0)
{
if (isBlocking(x + xa - width, y + ya, xa, 0)) collide = true;
else if (isBlocking(x + xa + width, y + ya, xa, 0)) collide = true;
else if (isBlocking(x + xa - width, y + ya + 1, xa, ya)) collide = true;
else if (isBlocking(x + xa + width, y + ya + 1, xa, ya)) collide = true;
}
if (ya < 0)
{
if (isBlocking(x + xa, y + ya - height, xa, ya)) collide = true;
else if (collide || isBlocking(x + xa - width, y + ya - height, xa, ya)) collide = true;
else if (collide || isBlocking(x + xa + width, y + ya - height, xa, ya)) collide = true;
}
if (xa > 0)
{
if (isBlocking(x + xa + width, y + ya - height, xa, ya)) collide = true;
if (isBlocking(x + xa + width, y + ya - height / 2, xa, ya)) collide = true;
if (isBlocking(x + xa + width, y + ya, xa, ya)) collide = true;
if (avoidCliffs && onGround && !world.level.isBlocking((int) ((x + xa + width) / 16), (int) ((y) / 16 + 1), xa, 1)) collide = true;
}
if (xa < 0)
{
if (isBlocking(x + xa - width, y + ya - height, xa, ya)) collide = true;
if (isBlocking(x + xa - width, y + ya - height / 2, xa, ya)) collide = true;
if (isBlocking(x + xa - width, y + ya, xa, ya)) collide = true;
if (avoidCliffs && onGround && !world.level.isBlocking((int) ((x + xa - width) / 16), (int) ((y) / 16 + 1), xa, 1)) collide = true;
}
if (collide)
{
if (xa < 0)
{
x = (int) ((x - width) / 16) * 16 + width;
this.xa = 0;
}
if (xa > 0)
{
x = (int) ((x + width) / 16 + 1) * 16 - width - 1;
this.xa = 0;
}
if (ya < 0)
{
y = (int) ((y - height) / 16) * 16 + height;
jumpTime = 0;
this.ya = 0;
}
if (ya > 0)
{
y = (int) (y / 16 + 1) * 16 - 1;
onGround = true;
}
return false;
}
else
{
x += xa;
y += ya;
return true;
}
}
private boolean isBlocking(float _x, float _y, float xa, float ya)
{
int x = (int) (_x / 16);
int y = (int) (_y / 16);
if (x == (int) (this.x / 16) && y == (int) (this.y / 16)) return false;
boolean blocking = world.level.isBlocking(x, y, xa, ya);
byte block = world.level.getBlock(x, y);
return blocking;
}
public void bumpCheck(int xTile, int yTile)
{
if (x + width > xTile * 16 && x - width < xTile * 16 + 16 && yTile==(int)((y-1)/16))
{
facing = -world.mario.facing;
ya = -10;
}
}
}

View File

@@ -0,0 +1,40 @@
package dk.itu.mario.engine.sprites;
import dk.itu.mario.engine.Art;
public class Particle extends Sprite
{
public int life;
public Particle(int x, int y, float xa, float ya)
{
this(x, y, xa, ya, (int)(Math.random()*2), 0);
}
public Particle(int x, int y, float xa, float ya, int xPic, int yPic)
{
sheet = Art.particles;
this.x = x;
this.y = y;
this.xa = xa;
this.ya = ya;
this.xPic = xPic;
this.yPic = yPic;
this.xPicO = 4;
this.yPicO = 4;
wPic = 8;
hPic = 8;
life = 10;
}
public void move()
{
if (life--<0) Sprite.spriteContext.removeSprite(this);
x+=xa;
y+=ya;
ya*=0.95f;
ya+=3;
}
}

View File

@@ -0,0 +1,370 @@
package dk.itu.mario.engine.sprites;
import dk.itu.mario.engine.Art;
import dk.itu.mario.scene.LevelScene;
public class Shell extends Sprite
{
private static float GROUND_INERTIA = 0.89f;
private static float AIR_INERTIA = 0.89f;
private float runTime;
private boolean onGround = false;
private int width = 4;
int height = 24;
private LevelScene world;
public int facing;
public boolean avoidCliffs = false;
public int anim;
public boolean dead = false;
private int deadTime = 0;
public boolean carried;
public Shell(LevelScene world, float x, float y, int type)
{
sheet = Art.enemies;
this.x = x;
this.y = y;
this.world = world;
xPicO = 8;
yPicO = 31;
yPic = type;
height = 12;
facing = 0;
wPic = 16;
xPic = 4;
ya = -5;
}
public boolean fireballCollideCheck(Fireball fireball)
{
if (deadTime != 0) return false;
float xD = fireball.x - x;
float yD = fireball.y - y;
if (xD > -16 && xD < 16)
{
if (yD > -height && yD < fireball.height)
{
if (facing!=0) return true;
world.sound.play(Art.samples[Art.SAMPLE_MARIO_KICK], this, 1, 1, 1);
xa = fireball.facing * 2;
ya = -5;
if (spriteTemplate != null) spriteTemplate.isDead = true;
deadTime = 100;
hPic = -hPic;
yPicO = -yPicO + 16;
return true;
}
}
return false;
}
public void collideCheck()
{
if (carried || dead || deadTime>0) return;
float xMarioD = world.mario.x - x;
float yMarioD = world.mario.y - y;
float w = 16;
if (xMarioD > -16 && xMarioD < 16)
{
if (yMarioD > -height && yMarioD < world.mario.height)
{
if (world.mario.ya > 0 && yMarioD <= 0 && (!world.mario.onGround || !world.mario.wasOnGround))
{
world.mario.stomp(this);
if (facing != 0)
{
xa = 0;
facing = 0;
}
else
{
facing = world.mario.facing;
}
}
else
{
if (facing != 0)
{
world.mario.getHurt(this);
}
else
{
world.mario.kick(this);
facing = world.mario.facing;
}
}
}
}
}
public void move()
{
if (y > world.level.getHeight() * 16 + 16 && deadTime == 0)
{
die();
spriteContext.removeSprite(this);
return;
}
if (carried)
{
world.checkShellCollide(this);
return;
}
if (deadTime > 0)
{
deadTime--;
if (deadTime == 0)
{
deadTime = 1;
for (int i = 0; i < 8; i++)
{
world.addSprite(new Sparkle((int) (x + Math.random() * 16 - 8) + 4, (int) (y - Math.random() * 8) + 4, (float) (Math.random() * 2 - 1), (float) Math.random() * -1, 0, 1, 5));
}
spriteContext.removeSprite(this);
}
x += xa;
y += ya;
ya *= 0.95;
ya += 1;
return;
}
if (facing != 0) anim++;
float sideWaysSpeed = 11f;
// float sideWaysSpeed = onGround ? 2.5f : 1.2f;
if (xa > 2)
{
facing = 1;
}
if (xa < -2)
{
facing = -1;
}
xa = facing * sideWaysSpeed;
if (facing != 0)
{
world.checkShellCollide(this);
}
xFlipPic = facing == -1;
runTime += (Math.abs(xa)) + 5;
xPic = (anim / 2) % 4 + 3;
if (!move(xa, 0))
{
world.sound.play(Art.samples[Art.SAMPLE_SHELL_BUMP], this, 1, 1, 1);
facing = -facing;
}
onGround = false;
move(0, ya);
ya *= 0.85f;
if (onGround)
{
xa *= GROUND_INERTIA;
}
else
{
xa *= AIR_INERTIA;
}
if (!onGround)
{
ya += 2;
}
}
private boolean move(float xa, float ya)
{
while (xa > 8)
{
if (!move(8, 0)) return false;
xa -= 8;
}
while (xa < -8)
{
if (!move(-8, 0)) return false;
xa += 8;
}
while (ya > 8)
{
if (!move(0, 8)) return false;
ya -= 8;
}
while (ya < -8)
{
if (!move(0, -8)) return false;
ya += 8;
}
boolean collide = false;
if (ya > 0)
{
if (isBlocking(x + xa - width, y + ya, xa, 0)) collide = true;
else if (isBlocking(x + xa + width, y + ya, xa, 0)) collide = true;
else if (isBlocking(x + xa - width, y + ya + 1, xa, ya)) collide = true;
else if (isBlocking(x + xa + width, y + ya + 1, xa, ya)) collide = true;
}
if (ya < 0)
{
if (isBlocking(x + xa, y + ya - height, xa, ya)) collide = true;
else if (collide || isBlocking(x + xa - width, y + ya - height, xa, ya)) collide = true;
else if (collide || isBlocking(x + xa + width, y + ya - height, xa, ya)) collide = true;
}
if (xa > 0)
{
if (isBlocking(x + xa + width, y + ya - height, xa, ya)) collide = true;
if (isBlocking(x + xa + width, y + ya - height / 2, xa, ya)) collide = true;
if (isBlocking(x + xa + width, y + ya, xa, ya)) collide = true;
if (avoidCliffs && onGround && !world.level.isBlocking((int) ((x + xa + width) / 16), (int) ((y) / 16 + 1), xa, 1)) collide = true;
}
if (xa < 0)
{
if (isBlocking(x + xa - width, y + ya - height, xa, ya)) collide = true;
if (isBlocking(x + xa - width, y + ya - height / 2, xa, ya)) collide = true;
if (isBlocking(x + xa - width, y + ya, xa, ya)) collide = true;
if (avoidCliffs && onGround && !world.level.isBlocking((int) ((x + xa - width) / 16), (int) ((y) / 16 + 1), xa, 1)) collide = true;
}
if (collide)
{
if (xa < 0)
{
x = (int) ((x - width) / 16) * 16 + width;
this.xa = 0;
}
if (xa > 0)
{
x = (int) ((x + width) / 16 + 1) * 16 - width - 1;
this.xa = 0;
}
if (ya < 0)
{
y = (int) ((y - height) / 16) * 16 + height;
this.ya = 0;
}
if (ya > 0)
{
y = (int) (y / 16 + 1) * 16 - 1;
onGround = true;
}
return false;
}
else
{
x += xa;
y += ya;
return true;
}
}
private boolean isBlocking(float _x, float _y, float xa, float ya)
{
int x = (int) (_x / 16);
int y = (int) (_y / 16);
if (x == (int) (this.x / 16) && y == (int) (this.y / 16)) return false;
boolean blocking = world.level.isBlocking(x, y, xa, ya);
byte block = world.level.getBlock(x, y);
if (blocking && ya == 0 && xa!=0)
{
world.bump(x, y, true);
}
return blocking;
}
public void bumpCheck(int xTile, int yTile)
{
if (x + width > xTile * 16 && x - width < xTile * 16 + 16 && yTile == (int) ((y - 1) / 16))
{
facing = -world.mario.facing;
ya = -10;
}
}
public void die()
{
dead = true;
carried = false;
xa = -facing * 2;
ya = -5;
deadTime = 100;
if(world.recorder != null)
world.recorder.killRecord(this);
}
public boolean shellCollideCheck(Shell shell)
{
if (deadTime != 0) return false;
float xD = shell.x - x;
float yD = shell.y - y;
if (xD > -16 && xD < 16)
{
if (yD > -height && yD < shell.height)
{
world.sound.play(Art.samples[Art.SAMPLE_MARIO_KICK], this, 1, 1, 1);
if (world.mario.carried == shell || world.mario.carried == this)
{
world.mario.carried = null;
}
die();
shell.die();
return true;
}
}
return false;
}
public void release(Mario mario)
{
carried = false;
facing = mario.facing;
x += facing * 8;
}
}

View File

@@ -0,0 +1,46 @@
package dk.itu.mario.engine.sprites;
import dk.itu.mario.engine.Art;
public class Sparkle extends Sprite
{
public int life;
public int xPicStart;
public Sparkle(int x, int y, float xa, float ya)
{
this(x, y, xa, ya, (int)(Math.random()*2), 0, 5);
}
public Sparkle(int x, int y, float xa, float ya, int xPic, int yPic, int timeSpan)
{
sheet = Art.particles;
this.x = x;
this.y = y;
this.xa = xa;
this.ya = ya;
this.xPic = xPic;
xPicStart = xPic;
this.yPic = yPic;
this.xPicO = 4;
this.yPicO = 4;
wPic = 8;
hPic = 8;
life = 10+(int)(Math.random()*timeSpan);
}
public void move()
{
if (life>10)
xPic = 7;
else
xPic = xPicStart+(10-life)*4/10;
if (life--<0) Sprite.spriteContext.removeSprite(this);
x+=xa;
y+=ya;
}
}

View File

@@ -0,0 +1,117 @@
package dk.itu.mario.engine.sprites;
import java.awt.Graphics;
import java.awt.Image;
import dk.itu.mario.engine.sonar.SoundSource;
public class Sprite implements SoundSource
{
public static SpriteContext spriteContext;
public float xOld, yOld, x, y, xa, ya;
public int xPic, yPic;
public int wPic = 32;
public int hPic = 32;
public int xPicO, yPicO;
public boolean xFlipPic = false;
public boolean yFlipPic = false;
public Image[][] sheet;
public boolean visible = true;
public int layer = 1;
public SpriteTemplate spriteTemplate;
public void move()
{
x+=xa;
y+=ya;
}
public void render(Graphics og, float alpha)
{
if (!visible) return;
int xPixel = (int)(xOld+(x-xOld)*alpha)-xPicO;
int yPixel = (int)(yOld+(y-yOld)*alpha)-yPicO;
og.drawImage(sheet[xPic][yPic], xPixel+(xFlipPic?wPic:0), yPixel+(yFlipPic?hPic:0), xFlipPic?-wPic:wPic, yFlipPic?-hPic:hPic, null);
}
/* private void blit(Graphics og, Image bitmap, int x0, int y0, int x1, int y1, int w, int h)
{
if (!xFlipPic)
{
if (!yFlipPic)
{
og.drawImage(bitmap, x0, y0, x0+w, y0+h, x1, y1, x1+w, y1+h, null);
}
else
{
og.drawImage(bitmap, x0, y0, x0+w, y0+h, x1, y1+h, x1+w, y1, null);
}
}
else
{
if (!yFlipPic)
{
og.drawImage(bitmap, x0, y0, x0+w, y0+h, x1+w, y1, x1, y1+h, null);
}
else
{
og.drawImage(bitmap, x0, y0, x0+w, y0+h, x1+w, y1+h, x1, y1, null);
}
}
}*/
public final void tick()
{
xOld = x;
yOld = y;
move();
}
public final void tickNoMove()
{
xOld = x;
yOld = y;
}
public float getX(float alpha)
{
return (xOld+(x-xOld)*alpha)-xPicO;
}
public float getY(float alpha)
{
return (yOld+(y-yOld)*alpha)-yPicO;
}
public void collideCheck()
{
}
public void bumpCheck(int xTile, int yTile)
{
}
public boolean shellCollideCheck(Shell shell)
{
return false;
}
public void release(Mario mario)
{
}
public boolean fireballCollideCheck(Fireball fireball)
{
return false;
}
}

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