A lot of comments, assets update
49
.classpath
Normal file
@ -0,0 +1,49 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<classpath>
|
||||
<classpathentry kind="src" output="target/classes" path="src/main/java">
|
||||
<attributes>
|
||||
<attribute name="optional" value="true"/>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry excluding="**" kind="src" output="target/classes" path="src/main/resources">
|
||||
<attributes>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry kind="src" output="target/test-classes" path="src/test/java">
|
||||
<attributes>
|
||||
<attribute name="optional" value="true"/>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
<attribute name="test" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8">
|
||||
<attributes>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
|
||||
<attributes>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry kind="src" path="target/generated-sources/annotations">
|
||||
<attributes>
|
||||
<attribute name="optional" value="true"/>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
<attribute name="ignore_optional_problems" value="true"/>
|
||||
<attribute name="m2e-apt" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry kind="src" output="target/test-classes" path="target/generated-test-sources/test-annotations">
|
||||
<attributes>
|
||||
<attribute name="optional" value="true"/>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
<attribute name="ignore_optional_problems" value="true"/>
|
||||
<attribute name="m2e-apt" value="true"/>
|
||||
<attribute name="test" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry kind="output" path="target/classes"/>
|
||||
</classpath>
|
34
.project
Normal file
@ -0,0 +1,34 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>DanmakuProject</name>
|
||||
<comment></comment>
|
||||
<projects>
|
||||
</projects>
|
||||
<buildSpec>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.jdt.core.javabuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.m2e.core.maven2Builder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||
<nature>org.eclipse.m2e.core.maven2Nature</nature>
|
||||
</natures>
|
||||
<filteredResources>
|
||||
<filter>
|
||||
<id>1640019058211</id>
|
||||
<name></name>
|
||||
<type>30</type>
|
||||
<matcher>
|
||||
<id>org.eclipse.core.resources.regexFilterMatcher</id>
|
||||
<arguments>node_modules|.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__</arguments>
|
||||
</matcher>
|
||||
</filter>
|
||||
</filteredResources>
|
||||
</projectDescription>
|
4
.settings/org.eclipse.core.resources.prefs
Normal file
@ -0,0 +1,4 @@
|
||||
eclipse.preferences.version=1
|
||||
encoding//src/main/java=UTF-8
|
||||
encoding//src/main/resources=UTF-8
|
||||
encoding/<project>=UTF-8
|
2
.settings/org.eclipse.jdt.apt.core.prefs
Normal file
@ -0,0 +1,2 @@
|
||||
eclipse.preferences.version=1
|
||||
org.eclipse.jdt.apt.aptEnabled=false
|
9
.settings/org.eclipse.jdt.core.prefs
Normal file
@ -0,0 +1,9 @@
|
||||
eclipse.preferences.version=1
|
||||
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
|
||||
org.eclipse.jdt.core.compiler.compliance=1.8
|
||||
org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled
|
||||
org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
|
||||
org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=ignore
|
||||
org.eclipse.jdt.core.compiler.processAnnotations=disabled
|
||||
org.eclipse.jdt.core.compiler.release=disabled
|
||||
org.eclipse.jdt.core.compiler.source=1.8
|
4
.settings/org.eclipse.m2e.core.prefs
Normal file
@ -0,0 +1,4 @@
|
||||
activeProfiles=
|
||||
eclipse.preferences.version=1
|
||||
resolveWorkspaceProjects=true
|
||||
version=1
|
17
README.md
Normal file
@ -0,0 +1,17 @@
|
||||
# DanmakuProject
|
||||
|
||||
This is made for a school project. It uses SDL2 under Java using JNA library.
|
||||
The main bindings are from libjsdl which is an attempt to create an interface for SDL2 using JNA
|
||||
but it lacks documentation and demonstration (still a great project). Some SDL2_mixer bindings are
|
||||
also created using JNA, which is not part of the libjsdl. (see Audio.java)
|
||||
|
||||
I hope this proves to be a good demonstration for using libjsdl and JNA.
|
||||
|
||||
## Credits:
|
||||
* Furkan Mudanyalı (Code, planning, execution etc.)
|
||||
* graphLoom, (Music, assets)
|
||||
|
||||
### Further Credits:
|
||||
* libjsdl contributors (especially shinedeveloper for a loot of bindings)
|
||||
* SDL2 contributors
|
||||
* SDL2_mixer contributors
|
BIN
assets/bullets/bullete-big.bmp
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
assets/bullets/bulletp-big.bmp
Normal file
After Width: | Height: | Size: 2.1 KiB |
BIN
assets/bullets/bulletp.bmp
Normal file
After Width: | Height: | Size: 970 B |
BIN
assets/enemies/guardian.bmp
Normal file
After Width: | Height: | Size: 1.8 KiB |
BIN
assets/enemies/guardianbig.bmp
Normal file
After Width: | Height: | Size: 16 KiB |
Before Width: | Height: | Size: 4.1 KiB |
BIN
assets/shmap.bmp
Before Width: | Height: | Size: 720 KiB After Width: | Height: | Size: 540 KiB |
Before Width: | Height: | Size: 2.0 MiB After Width: | Height: | Size: 1.5 MiB |
@ -33,7 +33,7 @@ import javax.sound.sampled.AudioSystem;
|
||||
/**
|
||||
* <h3>Audio Class</h3>
|
||||
*
|
||||
* This class is a native wrapper for SDL2_Mixer,
|
||||
* This class is a native JNA wrapper for SDL2_Mixer,
|
||||
* it also contains some additional methods
|
||||
*
|
||||
* @author Furkan Mudanyali
|
||||
@ -127,14 +127,21 @@ public class Audio {
|
||||
public static int Mix_PlayChannel(int channel, Pointer chunk, int loops){
|
||||
return Mix_PlayChannelTimed(channel, chunk, loops, -1);
|
||||
}
|
||||
|
||||
// Methods
|
||||
|
||||
/**
|
||||
* Returns WAV music length in milliseconds.
|
||||
*
|
||||
* <p>
|
||||
*
|
||||
* Credits to mdma from stackoverflow
|
||||
* <p>
|
||||
* https://stackoverflow.com/a/3009973
|
||||
*
|
||||
* @param filepath WAV file path
|
||||
* @return length in milliseconds
|
||||
* @return length in milliseconds, -1 if can't
|
||||
* open file.
|
||||
*/
|
||||
public static long getMusicLengthInMilliseconds(String filepath){
|
||||
try {
|
||||
|
@ -21,10 +21,25 @@ import java.io.File;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* @param fileName filename to get path of
|
||||
* @return path to the asset in the assets folder.
|
||||
* <h3>File Loader Class</h3>
|
||||
*
|
||||
* A class that contains static methods for file path
|
||||
* operations for SDL2. Since SDL2 cannot access the
|
||||
* virtual filesystem inside the .jar package, SDL2 files
|
||||
* must be kept in a seperate folder along with the .jar.
|
||||
*
|
||||
* @author Furkan Mudanyali
|
||||
* @version 1.0.0
|
||||
* @since 2021-12-01
|
||||
*/
|
||||
public class FileLoader {
|
||||
/**
|
||||
* Returns absolute path to the file from the assets folder.
|
||||
*
|
||||
* @param fileName filename to get path of
|
||||
* @return path to the asset in the assets folder,
|
||||
* null on any kind of I/O error.
|
||||
*/
|
||||
public static String getFilePath(String fileName){
|
||||
try{
|
||||
String protocol = FileLoader.class.getResource("").getProtocol();
|
||||
@ -35,7 +50,7 @@ public class FileLoader {
|
||||
}
|
||||
return System.getProperty("user.dir") + "/assets/" + fileName;
|
||||
} catch (Exception e){
|
||||
return "could not get filepath";
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
@ -20,13 +20,28 @@ package com.fmudanyali;
|
||||
import static org.libsdl.api.keyboard.SdlKeyboard.*;
|
||||
import com.sun.jna.ptr.ByteByReference;
|
||||
|
||||
/**
|
||||
* <h3>Keyboard Class</h3>
|
||||
*
|
||||
* A class to simplify keyboard functions.
|
||||
*
|
||||
* @author Furkan Mudanyali
|
||||
* @version 1.0.0
|
||||
* @since 2021-12-01
|
||||
*/
|
||||
public class Keyboard {
|
||||
// Basically array pointer
|
||||
public static ByteByReference keyboard = new ByteByReference();
|
||||
|
||||
public static void getKeyboardState(){
|
||||
keyboard = SDL_GetKeyboardState(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if given index of the keyboard array is true or not.
|
||||
*
|
||||
* @param key Index of the key in the keyboard array.
|
||||
* @return true if key is pressed, false if not.
|
||||
*/
|
||||
public static boolean getKeyState(int key){
|
||||
return keyboard.getPointer().getByte(key) == 1;
|
||||
}
|
||||
|
@ -21,23 +21,49 @@ import com.fmudanyali.scenes.*;
|
||||
import java.util.Stack;
|
||||
import org.libsdl.api.event.events.SDL_Event;
|
||||
|
||||
/**
|
||||
* <h3>Main Class</h3>
|
||||
* This is the starting point of the application.
|
||||
*
|
||||
* @author Furkan Mudanyali
|
||||
* @version 1.0.0
|
||||
* @since 2021-12-01
|
||||
*/
|
||||
public class Main {
|
||||
public static SDL_Event e = new SDL_Event();
|
||||
public static boolean exit = false;
|
||||
public static Stack<Scene> scenes = new Stack<>();
|
||||
public static void main(String[] args) throws Exception{
|
||||
/*
|
||||
Restart JVM if on macOS and it hasn't been launched
|
||||
with -XStartOnFirstThread arg. Needed for SDL to be
|
||||
able to create a window and show it on macOS as macOS
|
||||
ignores windows that are not opened by the first thread
|
||||
of the application for safety measures. Took me days
|
||||
to track the bug.
|
||||
*/
|
||||
if (RestartJVM.restartJVM()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Open audio device with basic defaults.
|
||||
Audio.Mix_OpenAudio(44100, Audio.MIX_DEFAULT_FORMAT, 2, 2048);
|
||||
// Push main menu to the scenes stack.
|
||||
scenes.push(new MainMenu());
|
||||
|
||||
// Each loop means a frame of the game.
|
||||
while(!scenes.empty() && !exit){
|
||||
// Calculate delta time, between last frame
|
||||
// and this frame.
|
||||
Time.Tick();
|
||||
Keyboard.getKeyboardState();
|
||||
// Call the loop function of the scene on the
|
||||
// top of the scenes stack.
|
||||
scenes.peek().loop();
|
||||
}
|
||||
// Exit is set to true manually to make sure the existing threads
|
||||
// are stopped, not really necessary as System.exit should close
|
||||
// those lingering threads but better be safe than sorry.
|
||||
exit = true;
|
||||
System.exit(0);
|
||||
}
|
||||
|
@ -33,24 +33,50 @@ import static org.libsdl.api.hints.SdlHintsConst.*;
|
||||
import static org.libsdl.api.hints.SdlHints.*;
|
||||
import static org.libsdl.api.render.SdlRender.SDL_RenderSetLogicalSize;
|
||||
|
||||
/**
|
||||
* <h3>Render Class</h3>
|
||||
* This class contains and initializes the SDL_Window and SDL_Renderer pointers,
|
||||
* it also has a method to create a continuous background from given texture.
|
||||
*
|
||||
* @author Furkan Mudanyali
|
||||
* @version 0.2.0
|
||||
* @since 2021-12-01
|
||||
*/
|
||||
public class Render {
|
||||
public static SDL_Window window;
|
||||
public static SDL_Renderer renderer;
|
||||
public static int bgw, bgh;
|
||||
|
||||
// Initialize SDL_Window and SDL_Renderer
|
||||
static {
|
||||
// Create window
|
||||
window = SDL_CreateWindow("DanmakuProject SDL2",
|
||||
SDL_WINDOWPOS_CENTERED(), SDL_WINDOWPOS_CENTERED(),
|
||||
WIDTH, HEIGHT, SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE | SDL_WINDOW_OPENGL);
|
||||
|
||||
// Hints for the renderer
|
||||
SDL_SetHint(SDL_HINT_RENDER_DRIVER, "opengl");
|
||||
SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "0");
|
||||
|
||||
// Create renderer
|
||||
renderer =
|
||||
SDL_CreateRenderer(Render.window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
|
||||
SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
|
||||
|
||||
// Make content scale according to the window size while maintaining the aspect ratio.
|
||||
SDL_RenderSetLogicalSize(renderer, Screen.WIDTH, Screen.HEIGHT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new row x col texture
|
||||
* from the given texture by stitching
|
||||
* it together.
|
||||
*
|
||||
* @param renderer Renderer to be used
|
||||
* @param texture Texture to be repeated
|
||||
* @param cols How many columns of the texture
|
||||
* @param rows How many rows of the texture
|
||||
* @return
|
||||
*/
|
||||
public static SDL_Texture createBackgroundFromTexture(
|
||||
SDL_Renderer renderer, SDL_Texture texture, int cols, int rows
|
||||
){
|
||||
|
@ -25,10 +25,22 @@ import java.io.InputStreamReader;
|
||||
import java.io.BufferedReader;
|
||||
|
||||
/**
|
||||
* Credits to kappa From
|
||||
* <h3>RestartJVM Class</h3>
|
||||
*
|
||||
* Has a single function that restarts JVM on macOS
|
||||
* if JVM is not launched with -XstartOnFirstThread arg
|
||||
* and launches it with it.
|
||||
*
|
||||
* <p>
|
||||
*
|
||||
* Credits to kappa from jvm-gaming.org
|
||||
* <p>
|
||||
* https://jvm-gaming.org/t/starting-jvm-on-mac-with-xstartonfirstthread-programmatically/57547
|
||||
*
|
||||
* @author kappa
|
||||
* @version 1.0.0
|
||||
* @since 2016-08-26
|
||||
*/
|
||||
|
||||
public class RestartJVM {
|
||||
public static boolean restartJVM() {
|
||||
|
||||
|
@ -27,6 +27,16 @@ import com.fmudanyali.characters.Player;
|
||||
|
||||
import static org.libsdl.api.render.SdlRender.*;
|
||||
|
||||
/**
|
||||
* <h3>Screen Class</h3>
|
||||
*
|
||||
* This class contains information about the game screen
|
||||
* It also has a method to set its background texture, and scroll it.
|
||||
*
|
||||
* @author Furkan Mudanyali
|
||||
* @version 0.2.0
|
||||
* @since 2021-12-08
|
||||
*/
|
||||
public class Screen {
|
||||
public static final int WIDTH = 960;
|
||||
public static final int HEIGHT = 540;
|
||||
@ -38,6 +48,7 @@ public class Screen {
|
||||
public static SDL_Texture tile, background, wallpaper;
|
||||
public static SDL_Surface tempSurface;
|
||||
|
||||
// Calculate positions and load wallpaper image.
|
||||
static {
|
||||
canvas.x = 12;
|
||||
canvas.y = 0;
|
||||
@ -54,6 +65,10 @@ public class Screen {
|
||||
tempSurface = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the given filepath to the background.
|
||||
* @param filename file path of the image.
|
||||
*/
|
||||
public static void makeBackground(String filename){
|
||||
// Load tile
|
||||
tempSurface = SDL_LoadBMP(FileLoader.getFilePath(filename));
|
||||
@ -64,6 +79,12 @@ public class Screen {
|
||||
background = Render.createBackgroundFromTexture(Render.renderer, tile, 1, 2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Scrolls the background vertically and horizontally.
|
||||
* Horizontal scroll is based on the player position to
|
||||
* create a parallax effect.
|
||||
* @param player
|
||||
*/
|
||||
public static void scroll(Player player){
|
||||
canvas.y = Math.floorMod(canvas.y - (int)(Time.deltaTime * 0.1), Render.bgh - canvas.h);
|
||||
canvas.x = (int)(12 + (player.position.x - 464)/13);
|
||||
|
@ -19,6 +19,16 @@ package com.fmudanyali;
|
||||
|
||||
import static org.libsdl.api.timer.SdlTimer.*;
|
||||
|
||||
/**
|
||||
* <h3>Time Class</h3>
|
||||
*
|
||||
* Calculates the time difference between this frame
|
||||
* and last frame, deltatime.
|
||||
*
|
||||
* @author Furkan Mudanyali
|
||||
* @version 1.0.0
|
||||
* @since 2021-12-03
|
||||
*/
|
||||
public class Time {
|
||||
public static int lastTime = 0;
|
||||
public static int currentTime = 0;
|
||||
|
@ -28,13 +28,27 @@ import org.libsdl.api.surface.SDL_Surface;
|
||||
import static org.libsdl.api.surface.SdlSurface.*;
|
||||
import static org.libsdl.api.render.SdlRender.*;
|
||||
|
||||
/**
|
||||
* <h3>PlayerBullet Class</h3>
|
||||
*
|
||||
* This class is for player made projectiles
|
||||
* that advance forward in the screen and explode
|
||||
* on enemy contact (to be implemented).
|
||||
*
|
||||
* @author Furkan Mudanyali
|
||||
* @version 0.4.0
|
||||
* @since 2021-12-22
|
||||
*/
|
||||
public class PlayerBullet {
|
||||
// Load the texture
|
||||
public static SDL_Surface tempSurface = SDL_LoadBMP(FileLoader.getFilePath("player/bullet.bmp"));
|
||||
public static SDL_Texture texture = SDL_CreateTextureFromSurface(Render.renderer, tempSurface);
|
||||
public SDL_Rect position = new SDL_Rect();
|
||||
public int width = 5;
|
||||
public int height = 12;
|
||||
|
||||
// Set the bullet position relative to the player position and given
|
||||
// offsets.
|
||||
public PlayerBullet(SDL_Rect playerPos, int xOffset, int yOffset){
|
||||
position.w = width;
|
||||
position.h = height;
|
||||
@ -42,6 +56,9 @@ public class PlayerBullet {
|
||||
position.y = playerPos.y - 6 - 3 - yOffset;
|
||||
}
|
||||
|
||||
/**
|
||||
* Advances the bullet on the screen.
|
||||
*/
|
||||
public void fly(){
|
||||
position.y = position.y - (int)(Time.deltaTime * 0.5);
|
||||
}
|
||||
|
@ -21,6 +21,16 @@ import org.libsdl.api.rect.SDL_Rect;
|
||||
import org.libsdl.api.render.SDL_Texture;
|
||||
import org.libsdl.api.surface.SDL_Surface;
|
||||
|
||||
/**
|
||||
* <h3>Character Superclass</h3>
|
||||
*
|
||||
* This class provides essentials that a character
|
||||
* should require.
|
||||
*
|
||||
* @author Furkan Mudanyali
|
||||
* @version 1.0.0
|
||||
* @since 2021-12-08
|
||||
*/
|
||||
public class Character {
|
||||
public SDL_Rect position = new SDL_Rect();
|
||||
public SDL_Texture texture = new SDL_Texture();
|
||||
|
@ -18,5 +18,5 @@
|
||||
package com.fmudanyali.characters;
|
||||
|
||||
public class Enemy extends Character {
|
||||
|
||||
// TODO: Implement
|
||||
}
|
||||
|
@ -32,7 +32,19 @@ import static org.libsdl.api.surface.SdlSurface.*;
|
||||
import static org.libsdl.api.render.SdlRender.*;
|
||||
import static org.libsdl.api.scancode.SDL_Scancode.*;
|
||||
|
||||
/**
|
||||
* <h3>Player Class</h3>
|
||||
*
|
||||
* This class extends on the character class and has all the
|
||||
* bells and whistles such as handling movement, shooting bullets,
|
||||
* animated sprites etc.
|
||||
*
|
||||
* @author Furkan Mudanyali
|
||||
* @version 0.9.0
|
||||
* @since 2021-12-08
|
||||
*/
|
||||
public class Player extends Character {
|
||||
// Variables
|
||||
public int lives;
|
||||
public double speed;
|
||||
public SDL_Texture propeller;
|
||||
@ -40,14 +52,16 @@ public class Player extends Character {
|
||||
public int frame = 0;
|
||||
public int roll = 0;
|
||||
public int cooldown = 0;
|
||||
|
||||
// New position rectangles for additional parts
|
||||
public SDL_Rect propellerPos = new SDL_Rect();
|
||||
public SDL_Rect shooterPos = new SDL_Rect();
|
||||
|
||||
// These rectangles are used for shifting
|
||||
// sprite animation.
|
||||
public SDL_Rect shipFrame = new SDL_Rect();
|
||||
public SDL_Rect propellerFrame = new SDL_Rect();
|
||||
public SDL_Rect shooterFrame = new SDL_Rect();
|
||||
|
||||
// Load the textures and set the positions.
|
||||
public Player(){
|
||||
lives = 3;
|
||||
tempSurface = SDL_LoadBMP(FileLoader.getFilePath("player/ship.bmp"));
|
||||
@ -167,7 +181,8 @@ public class Player extends Character {
|
||||
propellerFrame.x = 10;
|
||||
break;
|
||||
}
|
||||
|
||||
// Not a switch as DeltaTime does not provide
|
||||
// linear increase.
|
||||
if(roll > 0){
|
||||
shipFrame.x = shipFrame.y = 0;
|
||||
} if(roll > 15){
|
||||
@ -178,17 +193,23 @@ public class Player extends Character {
|
||||
} if(roll > 45){
|
||||
shipFrame.x = 32;
|
||||
}
|
||||
|
||||
// Frame is kept in 600 instead of 60
|
||||
// to be accurate with the varying framerate
|
||||
// animations.
|
||||
frame = (frame+10)%600;
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes positions depending on the keyboard state.
|
||||
*/
|
||||
public void movement(){
|
||||
// If shift is pressed, slow down the player.
|
||||
if(Keyboard.getKeyState(SDL_SCANCODE_LSHIFT)){
|
||||
speed = 1.5;
|
||||
}else{
|
||||
speed = 2;
|
||||
}
|
||||
|
||||
// Bunch of mathematical mumbo jumbo.
|
||||
if(Keyboard.getKeyState(SDL_SCANCODE_A) | Keyboard.getKeyState(SDL_SCANCODE_LEFT)){
|
||||
position.x = Math.max(position.x - (int)(speed * Time.deltaTime * 0.1), Screen.canvasPos.x - 5);
|
||||
shooterPos.x = Math.max(shooterPos.x - (int)(speed * Time.deltaTime * 0.1), Screen.canvasPos.x + 16 - 4 - 5);
|
||||
@ -227,7 +248,8 @@ public class Player extends Character {
|
||||
Game.playerBullets.add(new PlayerBullet(position, 17, 0));
|
||||
Game.playerBullets.add(new PlayerBullet(position, 21, 6));
|
||||
Game.playerBullets.add(new PlayerBullet(position, 25, 9));
|
||||
cooldown = 1;
|
||||
// Cooldown is used to prevent overshooting.
|
||||
cooldown = 3;
|
||||
}
|
||||
cooldown = Math.max(cooldown -1, 0);
|
||||
}
|
||||
|
@ -33,51 +33,85 @@ import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* <h3>Game Class</h3>
|
||||
*
|
||||
* This class extends on the Scene class and is mainly
|
||||
* the core of the game.
|
||||
*
|
||||
* @author Furkan Mudanyali
|
||||
* @version 0.1.0
|
||||
* @since 2021-12-04
|
||||
*/
|
||||
public class Game extends Scene {
|
||||
// Variables
|
||||
public static boolean escPressed = false;
|
||||
int kek = 0;
|
||||
private Player player = new Player();
|
||||
// Keeping track of the shots fired
|
||||
public static List<PlayerBullet> playerBullets = new ArrayList<>();
|
||||
// Thread for bg music
|
||||
private static Thread thread;
|
||||
// Create a runnable for the thread
|
||||
private static Runnable runnable = new Runnable() {
|
||||
public void run(){
|
||||
try {
|
||||
Mix_PlayMusic(Mix_LoadMUS(FileLoader.getFilePath("80-search-intro.wav")), 1);
|
||||
// Sleeping for the duration of the intro instead of checking if it stopped on a
|
||||
// loop saves a loooot of clock cycles.
|
||||
Thread.sleep(getMusicLengthInMilliseconds(FileLoader.getFilePath("80-search-intro.wav")));
|
||||
Mix_PlayMusic(Mix_LoadMUS(FileLoader.getFilePath("80-search-loop.wav")), -1);
|
||||
// Kill self because the last music will loop forever
|
||||
Thread.currentThread().interrupt();
|
||||
return;
|
||||
} catch(Exception e){
|
||||
// Will throw sleep interrupted, which is what we want.
|
||||
// Will throw sleep interrupted, which is exactly what we want.
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
public Game(){
|
||||
// Create the looping background
|
||||
Screen.makeBackground("shmap.bmp");
|
||||
// Set music volume to max
|
||||
Mix_VolumeMusic(128);
|
||||
// Try reading thread state, will throw exception for
|
||||
// the first time as the thread will not be initialized
|
||||
// at that time, which is perfectly expected.
|
||||
try {
|
||||
// Interrupt the thread if its running, this is needed
|
||||
// to keep only one thread alive at a time because if
|
||||
// the game is immediately quitted and a new game started,
|
||||
// the music will not get confused.
|
||||
if(thread.getState() != Thread.State.TERMINATED){
|
||||
thread.interrupt();
|
||||
}
|
||||
} catch (Exception e){
|
||||
//
|
||||
// Do nothing as I expect this behavior.
|
||||
}
|
||||
// Overwrite the the TERMINATED (or not initialized)
|
||||
// thread with a new thread with our runnable.
|
||||
thread = new Thread(runnable);
|
||||
// Start the thread.
|
||||
thread.start();
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loop(){
|
||||
// Handle events first
|
||||
while(SDL_PollEvent(Main.e) != 0){
|
||||
switch(Main.e.type){
|
||||
// If close button on the window is pressed.
|
||||
case SDL_QUIT:
|
||||
Main.exit = true;
|
||||
break;
|
||||
// If a key is pressed
|
||||
case SDL_KEYDOWN:
|
||||
switch(Main.e.key.keysym.sym){
|
||||
// If ESC is pressed, push pause menu to the scenes stack
|
||||
case SDLK_ESCAPE:
|
||||
// Needed to execute it only once per conventional key press
|
||||
if(!escPressed){
|
||||
Main.scenes.push(new PauseMenu());
|
||||
Mix_VolumeMusic(30);
|
||||
@ -86,6 +120,7 @@ public class Game extends Scene {
|
||||
break;
|
||||
}
|
||||
break;
|
||||
// If a key is released
|
||||
case SDL_KEYUP:
|
||||
switch(Main.e.key.keysym.sym){
|
||||
case SDLK_ESCAPE:
|
||||
@ -96,27 +131,31 @@ public class Game extends Scene {
|
||||
}
|
||||
}
|
||||
|
||||
// Do player movement thing and scroll the screen
|
||||
player.movement();
|
||||
Screen.scroll(player);
|
||||
|
||||
// Copying stuff to the renderer
|
||||
SDL_RenderClear(renderer);
|
||||
SDL_RenderCopy(renderer, Screen.wallpaper, null, null);
|
||||
SDL_RenderCopy(renderer, Screen.background, Screen.canvas, Screen.canvasPos);
|
||||
SDL_RenderCopy(renderer, player.texture, player.shipFrame, player.position);
|
||||
SDL_RenderCopy(renderer, player.propeller, player.propellerFrame, player.propellerPos);
|
||||
SDL_RenderCopy(renderer, player.shooter, player.shooterFrame, player.shooterPos);
|
||||
|
||||
// Iterate over the bullets on the screen
|
||||
for(Iterator<PlayerBullet> bulletIterator = playerBullets.iterator(); bulletIterator.hasNext();){
|
||||
PlayerBullet b = bulletIterator.next();
|
||||
// Move the bullet
|
||||
b.fly();
|
||||
// If the bullet is out of the screen, destroy it, else copy it to the renderer.
|
||||
if(b.position.y < 30){
|
||||
bulletIterator.remove();
|
||||
} else {
|
||||
SDL_RenderCopy(renderer, PlayerBullet.texture, null, b.position);
|
||||
}
|
||||
}
|
||||
|
||||
// Present the renderer to the window.
|
||||
SDL_RenderPresent(renderer);
|
||||
// Advance player sprite animation
|
||||
player.shiftFrame();
|
||||
}
|
||||
}
|
@ -17,6 +17,20 @@
|
||||
|
||||
package com.fmudanyali.scenes;
|
||||
|
||||
/**
|
||||
* <h3>Scene Class</h3>
|
||||
*
|
||||
* This class is an abstract for other scenes and makes able to
|
||||
* keep all the different kind of scenes on a single stack.
|
||||
*
|
||||
* @author Furkan Mudanyali
|
||||
* @version 1.0.0
|
||||
* @since 2021-12-04
|
||||
*/
|
||||
public abstract class Scene {
|
||||
/**
|
||||
* By design, this function will be
|
||||
* executed each game frame.
|
||||
*/
|
||||
public abstract void loop();
|
||||
}
|