diff --git a/assets/image.bmp b/assets/image.bmp
new file mode 100644
index 0000000..f118b02
Binary files /dev/null and b/assets/image.bmp differ
diff --git a/assets/person.bmp b/assets/person.bmp
new file mode 100644
index 0000000..f1851f2
Binary files /dev/null and b/assets/person.bmp differ
diff --git a/assets/tile.bmp b/assets/tile.bmp
new file mode 100644
index 0000000..403c083
Binary files /dev/null and b/assets/tile.bmp differ
diff --git a/lib/.DS_Store b/lib/.DS_Store
new file mode 100644
index 0000000..28b43b8
Binary files /dev/null and b/lib/.DS_Store differ
diff --git a/lib/jna-5.10.0.jar b/lib/jna-5.10.0.jar
new file mode 100644
index 0000000..e73c2c2
Binary files /dev/null and b/lib/jna-5.10.0.jar differ
diff --git a/lib/libjsdl-2.0.8-SNAPSHOT.jar b/lib/libjsdl-2.0.8-SNAPSHOT.jar
new file mode 100644
index 0000000..42068b6
Binary files /dev/null and b/lib/libjsdl-2.0.8-SNAPSHOT.jar differ
diff --git a/src/com/fmudanyali/FileLoader.java b/src/com/fmudanyali/FileLoader.java
new file mode 100644
index 0000000..55465f6
--- /dev/null
+++ b/src/com/fmudanyali/FileLoader.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2021 Furkan Mudanyali
+
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+package com.fmudanyali;
+
+import java.io.File;
+import java.util.Objects;
+
+/**
+ * @param fileName filename to get path of
+ * @return path to the asset in the assets folder.
+ */
+public class FileLoader {
+ public static String getFilePath(String fileName) throws Exception {
+ String protocol = FileLoader.class.getResource("").getProtocol();
+ if(Objects.equals(protocol, "jar")){
+ String jarPath = new File(FileLoader.class.getProtectionDomain().getCodeSource()
+ .getLocation().toURI()).getParentFile().getPath();
+ return jarPath + "/assets/" + fileName;
+ }
+ return System.getProperty("user.dir") + "/assets/" + fileName;
+ }
+}
\ No newline at end of file
diff --git a/src/com/fmudanyali/Game.java b/src/com/fmudanyali/Game.java
new file mode 100644
index 0000000..68472b5
--- /dev/null
+++ b/src/com/fmudanyali/Game.java
@@ -0,0 +1,151 @@
+/*
+ * Copyright (c) 2021 Furkan Mudanyali
+
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+package com.fmudanyali;
+
+import com.sun.jna.ptr.IntByReference;
+
+import org.libsdl.api.render.*;
+import org.libsdl.api.video.SDL_Window;
+import org.libsdl.api.surface.SDL_Surface;
+import org.libsdl.api.rect.SDL_Rect;
+import org.libsdl.api.event.events.SDL_Event;
+
+import static org.libsdl.api.render.SdlRender.*;
+import static org.libsdl.api.surface.SdlSurface.*;
+import static org.libsdl.api.video.SDL_WindowFlags.*;
+import static org.libsdl.api.video.SdlVideo.*;
+import static org.libsdl.api.SDL_SubSystem.*;
+import static org.libsdl.api.Sdl.*;
+import static org.libsdl.api.scancode.SDL_Scancode.*;
+//import static org.libsdl.api.error.SdlError.*;
+import static org.libsdl.api.event.SdlEvents.*;
+
+public class Game {
+ public static SDL_Window window;
+ public static SDL_Renderer renderer;
+ public static SDL_Texture texture, background, wallpaper, player;
+ public static SDL_Surface textureSurface = new SDL_Surface();
+
+ public static SDL_Rect viewport = new SDL_Rect();
+ public static SDL_Rect canvas = new SDL_Rect();
+ public static SDL_Rect playerPos = new SDL_Rect();
+
+ public static SDL_Event e = new SDL_Event();
+ public static boolean exit = false;
+
+ public static int WIDTH = 960;
+ public static int HEIGHT = 540;
+ public static int speed;
+
+ public static IntByReference bgwptr = new IntByReference();
+ public static IntByReference bghptr = new IntByReference();
+
+ public static void initialize() throws Exception{
+ // Initialize SDL
+ SDL_Init(SDL_INIT_VIDEO);
+ // Create Window
+ window = SDL_CreateWindow("SDL Java Test",
+ SDL_WINDOWPOS_CENTERED(), SDL_WINDOWPOS_CENTERED(),
+ WIDTH, HEIGHT, SDL_WINDOW_SHOWN);
+
+ // Create Renderer
+ renderer = SDL_CreateRenderer(window, -1,
+ SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
+
+ // Create surface to load BMP into
+ textureSurface = SDL_LoadBMP(FileLoader.getFilePath("image.bmp"));
+ // Create texture from the surface
+ wallpaper = SDL_CreateTextureFromSurface(renderer, textureSurface);
+ // Destroy the surface
+ textureSurface = null;
+ textureSurface = SDL_LoadBMP(FileLoader.getFilePath("tile.bmp"));
+ texture = SDL_CreateTextureFromSurface(renderer, textureSurface);
+ textureSurface = null;
+ textureSurface = SDL_LoadBMP(FileLoader.getFilePath("person.bmp"));
+ player = SDL_CreateTextureFromSurface(renderer, textureSurface);
+ textureSurface = null;
+ // Create a background double the width of the texture, used for scrolling animation
+ background = Render.createBackgroundFromTexture(renderer, texture, 12, 30);
+ SDL_QueryTexture(background, null, null, bgwptr, bghptr);
+ System.out.printf("Background: %dx%d%n", bgwptr.getValue(), bghptr.getValue());
+
+ // Dimensions of the viewport, its x and y is used for positioning
+ viewport.x = viewport.y = 0;
+ viewport.w = canvas.w = 384;
+ viewport.h = canvas.h = 480;
+ canvas.x = (WIDTH - canvas.w)/2;
+ canvas.y = (HEIGHT - canvas.h)/2;
+ playerPos.x = playerPos.y = viewport.w - 16;
+ playerPos.w = playerPos.h = 32;
+ System.out.printf("BG Res: %dx%d%n", bgwptr.getValue(), bghptr.getValue());
+ }
+
+ public static void loop(){
+ while(!exit){
+ Time.Tick();
+
+ while(SDL_PollEvent(e) != 0){
+ switch(e.type){
+ case SDL_QUIT:
+ exit = true;
+ break;
+ case SDL_KEYDOWN:
+ break;
+ }
+ }
+
+ Keyboard.getKeyboardState();
+
+ if(Keyboard.getKeyState(SDL_SCANCODE_LSHIFT)){
+ speed = 1;
+ }else{
+ speed = 2;
+ }
+
+ if(Keyboard.getKeyState(SDL_SCANCODE_A) | Keyboard.getKeyState(SDL_SCANCODE_LEFT)){
+ playerPos.x = Math.max(playerPos.x - (int)(speed * Time.deltaTime * 0.1), canvas.x);
+ }
+ if(Keyboard.getKeyState(SDL_SCANCODE_D) | Keyboard.getKeyState(SDL_SCANCODE_RIGHT)){
+ playerPos.x = Math.min(playerPos.x + (int)(speed * Time.deltaTime * 0.1), canvas.x + canvas.w - 32);
+ }
+ if(Keyboard.getKeyState(SDL_SCANCODE_W) | Keyboard.getKeyState(SDL_SCANCODE_UP)){
+ playerPos.y = Math.max(playerPos.y - (int)(speed * Time.deltaTime * 0.1), canvas.y);
+ }
+ if(Keyboard.getKeyState(SDL_SCANCODE_S) | Keyboard.getKeyState(SDL_SCANCODE_DOWN)){
+ playerPos.y = Math.min(playerPos.y + (int)(speed * Time.deltaTime * 0.1), canvas.y + canvas.h - 32);
+ }
+
+ viewport.y = Math.floorMod(viewport.y - (int)(Time.deltaTime * 0.1), bghptr.getValue() - canvas.h);
+
+ SDL_RenderClear(renderer);
+ SDL_RenderCopy(renderer, wallpaper, null, null);
+ SDL_RenderCopy(renderer, background, viewport, canvas);
+ SDL_RenderCopy(renderer, player, null, playerPos);
+ SDL_RenderPresent(renderer);
+
+ //System.out.printf("%d,%d%n", viewport.x, viewport.y);
+ }
+ }
+
+ public static void quit(){
+ SDL_DestroyTexture(texture);
+ SDL_DestroyRenderer(renderer);
+ SDL_DestroyWindow(window);
+ SDL_Quit();
+ }
+}
\ No newline at end of file
diff --git a/src/com/fmudanyali/Keyboard.java b/src/com/fmudanyali/Keyboard.java
new file mode 100644
index 0000000..7b1e2cc
--- /dev/null
+++ b/src/com/fmudanyali/Keyboard.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2021 Furkan Mudanyali
+
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+package com.fmudanyali;
+
+import static org.libsdl.api.keyboard.SdlKeyboard.*;
+import com.sun.jna.ptr.ByteByReference;
+
+public class Keyboard {
+ public static ByteByReference keyboard = new ByteByReference();
+
+ public static void getKeyboardState(){
+ keyboard = SDL_GetKeyboardState(null);
+ }
+
+ public static boolean getKeyState(int key){
+ return keyboard.getPointer().getByte(key) == 1;
+ }
+}
\ No newline at end of file
diff --git a/src/com/fmudanyali/Render.java b/src/com/fmudanyali/Render.java
new file mode 100644
index 0000000..d14f6b6
--- /dev/null
+++ b/src/com/fmudanyali/Render.java
@@ -0,0 +1,59 @@
+package com.fmudanyali;
+
+import com.sun.jna.ptr.IntByReference;
+
+import org.libsdl.api.render.SDL_Renderer;
+import org.libsdl.api.render.SDL_Texture;
+import org.libsdl.api.rect.SDL_Rect;
+
+import static org.libsdl.api.render.SdlRender.*;
+import static org.libsdl.api.pixels.SDL_PixelFormatEnum.*;
+
+public class Render {
+ public static SDL_Texture createBackgroundFromTexture(
+ SDL_Renderer renderer, SDL_Texture texture, int cols, int rows
+ ){
+ // Set minimum row and col to 1
+ if (rows < 1) rows = 1;
+ if (cols < 1) cols = 1;
+ // Create int pointers for Query Texture
+ IntByReference txwptr = new IntByReference();
+ IntByReference txhptr = new IntByReference();
+ // Query the texture for dimensions
+ SDL_QueryTexture(texture, null, null, txwptr, txhptr);
+ // Store them in ints
+ int txw = txwptr.getValue();
+ int txh = txhptr.getValue();
+ // Remove the pointers
+ txwptr = txhptr = null;
+ // Calculate background resolution
+ int bgw = txw * cols;
+ int bgh = txh * rows;
+ // Create background texture
+ SDL_Texture background = SDL_CreateTexture(
+ renderer, SDL_PIXELFORMAT_RGBA32, SDL_TEXTUREACCESS_TARGET, bgw, bgh);
+ // Set render target to background
+ SDL_SetRenderTarget(renderer, background);
+ // Create position rectangle for the texture
+ SDL_Rect txPos = new SDL_Rect();
+ txPos.x = txPos.y = 0;
+ txPos.w = txw;
+ txPos.h = txh;
+ // Loop for rows and columns
+ for(int i = 0; i < rows; ++i){
+ for(int j = 0; j < cols; ++j){
+ // Copy texture to the position
+ SDL_RenderCopy(renderer, texture, null, txPos);
+ // Increment x position
+ txPos.x += txw;
+ }
+ // Increment y position and clear x position
+ txPos.x = 0;
+ txPos.y += txh;
+ }
+ // Set render target back to window
+ SDL_SetRenderTarget(renderer, null);
+ // Return the background.
+ return background;
+ }
+}
diff --git a/src/com/fmudanyali/RestartJVM.java b/src/com/fmudanyali/RestartJVM.java
new file mode 100644
index 0000000..e81751a
--- /dev/null
+++ b/src/com/fmudanyali/RestartJVM.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2021 Furkan Mudanyali
+
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+package com.fmudanyali;
+
+import java.lang.management.ManagementFactory;
+import java.util.List;
+import java.util.ArrayList;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.BufferedReader;
+
+/**
+ * Credits to kappa From
+ * https://jvm-gaming.org/t/starting-jvm-on-mac-with-xstartonfirstthread-programmatically/57547
+ */
+
+public class RestartJVM {
+ public static boolean restartJVM() {
+
+ String osName = System.getProperty("os.name");
+
+ // if not a mac return false
+ if (!osName.startsWith("Mac") && !osName.startsWith("Darwin")) {
+ return false;
+ }
+
+ // get current jvm process pid
+ String pid = ManagementFactory.getRuntimeMXBean().getName().split("@")[0];
+ // get environment variable on whether XstartOnFirstThread is enabled
+ String env = System.getenv("JAVA_STARTED_ON_FIRST_THREAD_" + pid);
+
+ // if environment variable is "1" then XstartOnFirstThread is enabled
+ if (env != null && env.equals("1")) {
+ return false;
+ }
+
+ // restart jvm with -XstartOnFirstThread
+ String separator = System.getProperty("file.separator");
+ String classpath = System.getProperty("java.class.path");
+ String mainClass = System.getenv("JAVA_MAIN_CLASS_" + pid);
+ String jvmPath = System.getProperty("java.home") + separator + "bin" + separator + "java";
+
+ List inputArguments = ManagementFactory.getRuntimeMXBean().getInputArguments();
+
+ ArrayList jvmArgs = new ArrayList();
+
+ jvmArgs.add(jvmPath);
+ jvmArgs.add("-XstartOnFirstThread");
+ jvmArgs.addAll(inputArguments);
+ jvmArgs.add("-cp");
+ jvmArgs.add(classpath);
+ jvmArgs.add(mainClass);
+
+ // if you don't need console output, just enable these two lines
+ // and delete bits after it. This JVM will then terminate.
+ //ProcessBuilder processBuilder = new ProcessBuilder(jvmArgs);
+ //processBuilder.start();
+
+ try {
+ ProcessBuilder processBuilder = new ProcessBuilder(jvmArgs);
+ processBuilder.redirectErrorStream(true);
+ Process process = processBuilder.start();
+
+ InputStream is = process.getInputStream();
+ InputStreamReader isr = new InputStreamReader(is);
+ BufferedReader br = new BufferedReader(isr);
+ String line;
+
+ while ((line = br.readLine()) != null) {
+ System.out.println(line);
+ }
+
+ process.waitFor();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ return true;
+ }
+}
diff --git a/src/com/fmudanyali/Test.java b/src/com/fmudanyali/Test.java
new file mode 100644
index 0000000..abf4995
--- /dev/null
+++ b/src/com/fmudanyali/Test.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2021 Furkan Mudanyali
+
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+package com.fmudanyali;
+
+public class Test {
+ public static void main(String[] args) throws Exception{
+ if (RestartJVM.restartJVM()) {
+ return;
+ }
+
+ Game.initialize();
+ Game.loop();
+ Game.quit();
+ }
+}
\ No newline at end of file
diff --git a/src/com/fmudanyali/Time.java b/src/com/fmudanyali/Time.java
new file mode 100644
index 0000000..803f086
--- /dev/null
+++ b/src/com/fmudanyali/Time.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2021 Furkan Mudanyali
+
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+package com.fmudanyali;
+
+import static org.libsdl.api.timer.SdlTimer.*;
+
+public class Time {
+ public static int lastTime = 0;
+ public static int currentTime = 0;
+ public static int deltaTime = 0;
+
+ public static void Tick(){
+ lastTime = currentTime;
+ currentTime = SDL_GetTicks();
+ deltaTime = currentTime - lastTime;
+ }
+}