86 Commits
Author SHA1 Message Date
nortega 724c575c4e Bump version to v1.0 2026-07-09 15:02:08 +02:00
nortega 28ed600954 Port to C++. 2026-07-09 15:01:54 +02:00
nortega 978bf41ab0 Rewrite parts of CMakeLists.txt. 2026-03-31 11:17:27 +02:00
nortega 4046f6dfd5 Bump version to v0.6 2026-03-21 13:07:13 +01:00
nortega c038867810 Add planetary masses. 2026-03-21 13:05:28 +01:00
nortega abe90847ea Use floats for position in ship_init(). 2026-03-20 14:32:21 +01:00
nortega 1f3674b266 Bump version to v0.5. 2026-03-16 21:55:33 +01:00
nortega 2e5e37b0a5 Fix display transformation and star generation for fullscreen mode. 2026-03-16 21:49:02 +01:00
nortega 7cc8524811 Remove unnecessary header include. 2026-03-16 21:33:55 +01:00
nortega 55402c0c66 Update copyright headers. 2026-03-16 21:33:30 +01:00
nortega f1cdffba2b Add a starfield in the background.
This should help to better visualize the velocity of the ship.
2026-03-16 21:29:39 +01:00
nortega 0e5a4c89e5 Follow the ship. 2026-03-16 21:21:42 +01:00
nortega bb47dcc9f9 Implement zoom. 2026-03-16 21:17:23 +01:00
nortega 3d9c211737 Bump version to v0.4 2026-03-03 09:37:47 +01:00
nortega 4e7e37821e Link to license file. 2026-03-03 09:32:08 +01:00
nortega f520790f9c Change e-mail address. 2026-03-03 09:30:28 +01:00
nortega 44531ab24e Fix formatting of README.md 2026-03-03 09:28:44 +01:00
nortega c1139ddb81 Change README to markdown. 2026-03-03 09:26:50 +01:00
nortega da8d83de92 Remove fullscreen to-do item. 2026-03-03 09:23:36 +01:00
nortega bc6881f851 Revert "Move global variables to main()."
This reverts commit b842bd0095.
2026-03-03 09:22:16 +01:00
nortega b842bd0095 Move global variables to main().
Should not make variables global unnecessarily.
2026-03-03 09:20:50 +01:00
nortega bb28285794 Fix possible precision loss by converting to float. 2026-03-03 09:20:00 +01:00
nortega 6621decc09 Add fullscreen mode support. 2026-03-03 09:19:16 +01:00
nortega fd9fd453b3 Add help information for pause button. 2026-03-03 08:26:53 +01:00
nortega b0f4f6849d Update CMake minimum required version to 3.10
This is needed to build with modern versions of CMake.
2026-03-03 08:21:01 +01:00
nortega 8924741937 Remove from the TODO 2018-04-13 08:02:55 +02:00
nortega 63f950e26b Implement pause functionality. 2018-04-13 08:02:34 +02:00
nortega 349848ebf6 Remove extra 5.0 stuff (fix later). 2018-04-13 08:01:53 +02:00
nortega 395c3c854f Require minimum version of Allegro. 2018-04-04 11:55:02 +02:00
nortega a93e9a7b73 For compatibility with Debian systems.
For some reason they specify the minor version too, which is retarded.
2018-04-04 11:51:20 +02:00
nortega 29219bbc2c Added a TODO list. 2018-03-29 13:04:35 +02:00
nortega d343c5e5a0 Move help information further up. 2018-03-29 13:01:09 +02:00
nortega 17777e2178 No need to update the ship if we reset. 2018-03-29 12:58:37 +02:00
nortega 609d197227 Better description. 2018-03-29 12:56:01 +02:00
nortega e29a0bc7a3 Slower acceleration. 2018-03-29 12:55:48 +02:00
nortega 92e406bc74 Measure by pixel/second 2018-03-29 11:57:17 +02:00
nortega 2d64adf476 Put version in window title. 2018-03-29 01:06:15 +02:00
nortega ab10fcdf02 Reset simulation feature added. 2018-03-25 18:45:28 +02:00
nortega c51f34c888 Fully functional simulation.
I still need to add the restart feature.
2018-03-25 18:43:06 +02:00
nortega 85435fef8d Added help information. 2018-03-25 18:24:39 +02:00
nortega 8e10be3ea9 Forgot to update x and y variables. 2018-03-25 18:02:09 +02:00
nortega b41719855a Set ship turning correctly. 2018-03-25 17:57:37 +02:00
nortega 008ec2bd72 Added keyboard event source. 2018-03-25 17:57:21 +02:00
nortega 88f3a5f1a5 Added malfunctioning ship.
Currently it doesn't seem to be detecting the key preses.
2018-03-25 17:47:31 +02:00
nortega 80113d51ff Remove global variables.
Global variables are overall bad practice.
2018-03-25 17:14:44 +02:00
nortega 0faa83c162 Remove help and info from key list. 2018-03-25 17:04:14 +02:00
nortega 4dc7fbbf04 Create a ship object. 2018-03-25 16:59:03 +02:00
nortega a1406c4506 Included debug information. 2018-03-25 16:44:09 +02:00
nortega 86159b0b69 Initialize the primitives addon. 2018-03-25 16:42:00 +02:00
nortega fb023194e3 Add fast-math optimization for release builds. 2018-03-25 16:40:56 +02:00
nortega 5cefcd8554 Added section of v0.3. 2018-03-25 15:46:46 +02:00
nortega fa9a35444b Invalid keycodes also return 0 (but print a msg in DEBUG). 2018-03-25 15:34:53 +02:00
nortega d871bcec41 Implemented key_is_down() function. 2018-03-25 15:29:48 +02:00
nortega ea4f4a97b6 Keyboard input added. 2018-03-25 15:22:43 +02:00
nortega d57da20ec7 Created an event manager. 2018-03-25 14:53:40 +02:00
nortega b99e33fe52 A changelog file of previous releases. 2018-03-25 14:53:08 +02:00
nortega 768f80a362 Create a display. 2018-03-25 14:27:10 +02:00
nortega 8c19b96bb7 New install target. 2018-03-25 12:30:39 +02:00
nortega 1cdd5964f0 First steps. 2018-03-25 12:08:19 +02:00
nortega a54d54d993 Use floats for less precision (we don't need doubles). 2016-09-18 16:17:34 +02:00
Nicolás A. Ortega 8551012cac Update README.md 2014-10-30 15:46:23 -05:00
Deathsbreed 83e84ba74c Moved Windows class inside the SpaceShipSim class (for file simplicity). 2014-10-10 11:48:32 -05:00
Deathsbreed 7ed497892b Update README.md 2014-10-08 19:45:05 -05:00
Deathsbreed 091b9f704e Simplified compiling. 2014-10-08 19:44:41 -05:00
Deathsbreed 07a36e01e4 Added some getter/setter methods. 2014-10-01 12:10:05 -05:00
Deathsbreed a8303ba13c Removed '+' from the 'About' page. 2014-09-22 08:31:29 -05:00
Deathsbreed 5b577f3405 Update README.md 2014-09-20 18:56:25 -05:00
Deathsbreed efae00fd45 Changed README for compile information. 2014-09-20 18:53:20 -05:00
Deathsbreed d072de67dd Changing to using ant for compiling. 2014-09-20 18:52:10 -05:00
Nicolás A. Ortega bc6085609f Update README.md 2014-09-17 21:19:29 -05:00
Deathsbreed b78d4eef85 Removed some commented lines. 2014-05-31 17:42:09 -05:00
Deathsbreed a05307f38a Set version variable to prepare for the next version (I tend to forget that kind of stuff). 2014-05-28 10:15:20 -05:00
Deathsbreed 84dd04008f Added shortcut to reset. 2014-05-28 09:56:12 -05:00
Deathsbreed 574c562299 There is now a Window that opens to display information, and various new menu
items. There is also a shortcut to quit the application.
2014-05-28 09:38:05 -05:00
Deathsbreed 9f232d9e46 Added more menu items to the help menu that still don't work. It'll need some work. 2014-05-27 20:53:29 -05:00
Deathsbreed 390a1460f2 Added STUFF comments since I do not like blank spaces. 2014-05-27 20:45:42 -05:00
Deathsbreed b0360f7308 Added new not-finished class for About window. 2014-05-27 20:43:58 -05:00
Deathsbreed f6cfb9c0bc Added a Reset button, and a not working About button. 2014-05-27 20:43:11 -05:00
Deathsbreed d7911b01c5 KeyListener fixed! 2014-05-27 19:21:17 -05:00
Deathsbreed a511027e16 Got the menus working, now the KeyListener needs to be fixed. 2014-05-27 17:05:04 -05:00
Deathsbreed 2cc5153497 Added FIXME to corresponding section. 2014-05-27 08:21:20 -05:00
Deathsbreed e19278dfec Trying to create menu bar. 2014-05-27 08:15:09 -05:00
Deathsbreed 3174669ec3 Forget about the gitignore, it is fine. 2014-05-26 16:39:33 -05:00
Deathsbreed 6ddb1fd610 Seeing if I can stop .gitignore from appearing on the website 2014-05-26 16:38:41 -05:00
Deathsbreed 60e396102d Merge branch 'master' of https://github.com/Deathsbreed/SpaceShipSim 2014-05-26 16:36:21 -05:00
Deathsbreed 0c921ea7fd Trying to see if gitignore works 2014-05-26 16:35:29 -05:00
19 changed files with 1197 additions and 254 deletions
+3
View File
@@ -0,0 +1,3 @@
# Ignore build files
build/*
!build/.keep
+36
View File
@@ -0,0 +1,36 @@
# Change Log
## v1.0: Port to C++
- Port the bulk of the codebase to C++ for simplicity.
## v0.6: Planetary Masses
- Add planetary masses.
- Modify some of the constants.
## v0.5: Effects
- Added stars in background for a better sense of velocity.
- Viewport follows ship at center.
- Zoom functionality.
## v0.4: More functionality
- Fix acceleration.
- Add fullscreen support.
- Pause functionality.
## v0.3: Port to C
- Codebase ported to C for better performance.
## v0.2: Menu Bar
- Added a menu bar.
- Can reset the simulation.
## v1.0: First Release
- Basic simulation.
- Information printing.
+87
View File
@@ -0,0 +1,87 @@
# Copyright (C) 2026 Ortega Froysa, Nicolás <nicolas@ortegas.org>
# Author: Ortega Froysa, Nicolás <nicolas@ortegas.org>
#
# 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 <http://www.gnu.org/licenses/>.
cmake_minimum_required(VERSION 3.10)
project(spaceshipsim
VERSION 1.0
SPDX_LICENSE "GPL-3.0-or-later"
DESCRIPTION "A simulation of a 2D space ship in the frictionless environment of space."
HOMEPAGE_URL "https://code.ortegas.org/nortega/spaceshipsim"
LANGUAGES C CXX)
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE "release")
endif()
string(TOLOWER ${CMAKE_BUILD_TYPE} CMAKE_BUILD_TYPE)
message(STATUS "Build type: ${CMAKE_BUILD_TYPE}")
set(CMAKE_C_FLAGS "-std=c99 -Wall -Wextra -Werror")
set(CMAKE_C_FLAGS_DEBUG "-g -O0")
set(CMAKE_C_FLAGS_RELEASE "-O3 -ffast-math")
set(CMAKE_C_FLAGS_RELWITHDEBINFO "-g -O3 -ffast-math")
set(CMAKE_C_FLAGS_MINSIZEREL "-Os")
set(CMAKE_CXX_FLAGS "-std=c++11 -Wall -Wextra -Werror")
set(CMAKE_CXX_FLAGS_DEBUG "-g -O0")
set(CMAKE_CXX_FLAGS_RELEASE "-O3 -ffast-math")
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-g -O3 -ffast-math")
set(CMAKE_CXX_FLAGS_MINSIZEREL "-Os")
find_package(PkgConfig REQUIRED)
pkg_check_modules(ALLEG5 REQUIRED allegro-5>=5.1.9)
pkg_check_modules(ALLEG5-PRIM REQUIRED allegro_primitives-5)
pkg_check_modules(ALLEG5-FONT REQUIRED allegro_font-5)
include_directories(
SYSTEM ${ALLEG5_INCLUDE_DIRS})
set(SRCS
"src/event_manager.c"
"src/main.cpp"
"src/planet.cpp"
"src/ship.cpp"
"src/starfield.c"
)
set(HDRS
"src/event_manager.h"
"src/globals.h"
"src/planet.h"
"src/ship.h"
"src/starfield.h"
"src/vec.h"
)
add_definitions(-DVERSION="${PROJECT_VERSION}")
if(${CMAKE_BUILD_TYPE} STREQUAL "debug" OR ${CMAKE_BUILD_TYPE} STREQUAL "relwithdebinfo")
add_definitions(-DDEBUG)
else()
add_definitions(-DNDEBUG)
endif()
add_executable(${PROJECT_NAME} ${SRCS} ${HDRS})
target_link_libraries(${PROJECT_NAME}
m # math library
${ALLEG5_LIBRARIES}
${ALLEG5-PRIM_LIBRARIES}
${ALLEG5-FONT_LIBRARIES})
install(TARGETS ${PROJECT_NAME}
RUNTIME DESTINATION bin/
CONFIGURATIONS release minsizerel)
+37 -7
View File
@@ -1,10 +1,40 @@
SpaceShipSim
============
# SpaceShipSim
Space Ship Simulator is a basic 2D simulator of a spaceship in a frictionless environment. This program was made for educational purposes, and is meant to be quite simple.
This is a small simulation program of a space ship (with infinite fuel) in a
frictionless environment (space). The idea is to use it for educational
purposes.
To compile the source-code, go into the project src/ folder and run the following command:<br>
<code>$ javac spaceshipsim/SpaceShipSim.java</code>
## Compiling
<h4>Contributing</h4>
If you wish to contribute, feel free! Make sure to contact me at nicolas.ortega.froysa@gmail.com to give you permission to modify the project on Github. Or, you can make your own branch or fork this project!
In order to build this program you will require the following dependencies:
- GNU C and C++ compiler that supports C++11
- CMake 3.10 or higher
- Allegro 5
You can then compile the program via the following commands:
```bash
cd build/
cmake ..
make
```
This will create a release build with compiler optimizations. If you would like
a debug build then pass the `-DCMAKE_BUILD_TYPE=debug` flag to the `cmake`
command. If you would like to install then run `cmake` with the additional flag
`-DCMAKE_INSTALL_PREFIX=<install_dir>`. If you are installing as a user then
you may want to set the installation prefix to `/usr/local/`, and if you're
packaging then please consult your distribution's policies. With this you
should be able to run the `make install' target and install the binary.
## Contributing
If you would like to contribute to the project, send a patch file to my e-mail
address: [nicolas@ortegas.org](mailto:nicolas@ortegas.org).
## License
As educational software, unless otherwise noted, all files are licensed under
the terms & conditions of the GNU General Public License version 3 or greater
(see the [license file](LICENSE) for more information).
View File
+160
View File
@@ -0,0 +1,160 @@
/*
* Copyright (C) 2018,2026 Ortega Froysa, Nicolás <nicolas@ortegas.org>
* Author: Ortega Froysa, Nicolás <nicolas@ortegas.org>
*
* 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 <http://www.gnu.org/licenses/>.
*/
#include "event_manager.h"
#include "globals.h"
#ifdef DEBUG
# include <stdio.h>
#endif
#include <stddef.h>
#include <assert.h>
#include <allegro5/allegro.h>
static ALLEGRO_EVENT_QUEUE *event_queue = NULL;
static ALLEGRO_TIMER *timer = NULL;
static int keys[KEY_MAX];
int evnt_mngr_init(ALLEGRO_DISPLAY *display) {
assert(display);
if(!al_install_keyboard())
return 0;
#ifdef DEBUG
puts("[DEBUG] Initialized keyboard.");
#endif
timer = al_create_timer(1.0f / FPS);
if(!timer)
return 0;
#ifdef DEBUG
puts("[DEBUG] Initialized timer.");
#endif
event_queue = al_create_event_queue();
if(!event_queue) {
al_destroy_timer(timer);
return 0;
}
#ifdef DEBUG
puts("[DEBUG] Initialized event queue.");
#endif
al_register_event_source(event_queue,
al_get_display_event_source(display));
al_register_event_source(event_queue,
al_get_timer_event_source(timer));
al_register_event_source(event_queue,
al_get_keyboard_event_source());
al_start_timer(timer);
// set all keys to false at initialization
for(size_t i = 0; i < KEY_MAX; ++i)
keys[i] = 0;
return 1;
}
void evnt_mngr_deinit() {
if(al_is_keyboard_installed()) {
al_uninstall_keyboard();
#ifdef DEBUG
puts("[DEBUG] Uninstalled keyboard.");
#endif
}
if(timer) {
al_destroy_timer(timer);
#ifdef DEBUG
puts("[DEBUG] Destroyed timer.");
#endif
}
if(event_queue) {
al_destroy_event_queue(event_queue);
#ifdef DEBUG
puts("[DEBUG] Destroyed event queue.");
#endif
}
}
void set_key(int keycode, int value) {
switch(keycode) {
case ALLEGRO_KEY_UP:
keys[KEY_UP] = value;
break;
case ALLEGRO_KEY_DOWN:
keys[KEY_DOWN] = value;
break;
case ALLEGRO_KEY_LEFT:
keys[KEY_LEFT] = value;
break;
case ALLEGRO_KEY_RIGHT:
keys[KEY_RIGHT] = value;
break;
case ALLEGRO_KEY_R:
keys[KEY_RESET] = value;
break;
case ALLEGRO_KEY_F:
keys[KEY_FULLSCREEN] = value;
break;
case ALLEGRO_KEY_P:
keys[KEY_PAUSE] = value;
break;
case ALLEGRO_KEY_LSHIFT:
case ALLEGRO_KEY_RSHIFT:
keys[KEY_SHIFT] = value;
break;
case ALLEGRO_KEY_Z:
keys[KEY_ZOOM] = value;
break;
default:
break;
}
}
void handle_event() {
ALLEGRO_EVENT evnt;
al_wait_for_event(event_queue, &evnt);
do {
switch(evnt.type) {
case ALLEGRO_EVENT_TIMER:
redraw = 1;
break;
case ALLEGRO_EVENT_DISPLAY_CLOSE:
run = 0;
break;
case ALLEGRO_EVENT_KEY_DOWN:
if(evnt.keyboard.keycode == ALLEGRO_KEY_H)
show_help = !show_help;
else if(evnt.keyboard.keycode == ALLEGRO_KEY_I)
show_info = !show_info;
else if(evnt.keyboard.keycode == ALLEGRO_KEY_Q ||
evnt.keyboard.keycode == ALLEGRO_KEY_ESCAPE)
run = 0;
else
set_key(evnt.keyboard.keycode, 1);
break;
case ALLEGRO_EVENT_KEY_UP:
set_key(evnt.keyboard.keycode, 0);
break;
}
} while(al_get_next_event(event_queue, &evnt));
}
int key_is_down(int code) {
assert(code >= 0 && code <= KEY_MAX);
return keys[code];
}
+72
View File
@@ -0,0 +1,72 @@
/*
* Copyright (C) 2018,2026 Ortega Froysa, Nicolás <nicolas@ortegas.org>
* Author: Ortega Froysa, Nicolás <nicolas@ortegas.org>
*
* 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 <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <allegro5/allegro.h>
#ifdef __cplusplus
extern "C" {
#endif
enum {
KEY_UP = 0x0,
KEY_DOWN = 0x1,
KEY_LEFT = 0x2,
KEY_RIGHT = 0x3,
KEY_RESET = 0x4,
KEY_FULLSCREEN = 0x5,
KEY_PAUSE = 0x6,
KEY_ZOOM = 0x7,
KEY_SHIFT = 0x8,
KEY_MAX = 0x9
};
/**
* @brief Initialize the event handler.
*
* @param display A pointer to the display (used to get
* event source).
*
* @return 0 upon failure, 1 upon success.
*/
int evnt_mngr_init(ALLEGRO_DISPLAY *display);
/**
* @brief Deinitialize the event handler.
*/
void evnt_mngr_deinit();
/**
* @brief Handle the next event in the queue (wait if the
* queue is empty).
*/
void handle_event();
/**
* @brief Receive state of a key.
*
* @param code The key code.
*
* @return If down 1 will be returned, else 0.
*/
int key_is_down(int code);
#ifdef __cplusplus
}
#endif
+72
View File
@@ -0,0 +1,72 @@
/*
* Copyright (C) 2018,2026 Ortega Froysa, Nicolás <nicolas@ortegas.org>
* Author: Ortega Froysa, Nicolás <nicolas@ortegas.org>
*
* 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 <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <math.h>
#ifndef M_PI
# define M_PI 3.14159265f
#endif
#ifndef VERSION
# define VERSION "[version]"
#endif
#ifndef FPS
# define FPS 60.0f
#endif
#ifndef ACCEL
# define ACCEL 0.3f
#endif
#ifndef TURN_ACCEL
# define TURN_ACCEL (M_PI / FPS) // turn at pi radians / sec
#endif
#ifndef WINDOW_WIDTH
# define WINDOW_WIDTH 800
#endif
#ifndef WINDOW_HEIGHT
# define WINDOW_HEIGHT 600
#endif
#ifndef ZOOM_MIN
# define ZOOM_MIN 0.25f
#endif
#ifndef ZOOM_MAX
# define ZOOM_MAX 4.0f
#endif
#ifndef ZOOM_STEP
# define ZOOM_STEP 0.1f
#endif
#define RAD_TO_DEG(x) (x * 180 / M_PI)
#include <allegro5/allegro.h>
#ifdef __cplusplus
extern "C" {
#endif
extern int redraw; ///< Whether or not to redraw the screen.
extern int run; ///< Whether or not to continue running the simulation.
extern int show_help; ///< Whether or not to show the help info.
extern int show_info; ///< Whether or not to show simulation info.
#ifdef __cplusplus
}
#endif
+270
View File
@@ -0,0 +1,270 @@
/*
* Copyright (C) 2018,2026 Ortega Froysa, Nicolás <nicolas@ortegas.org>
* Author: Ortega Froysa, Nicolás <nicolas@ortegas.org>
*
* 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 <http://www.gnu.org/licenses/>.
*/
#include "globals.h"
#include "event_manager.h"
#include "ship.h"
#include "starfield.h"
#include "planet.h"
#include "vec.h"
int run;
int redraw;
int show_help;
int show_info;
#include <cstdlib>
#include <iostream>
#include <string>
#include <allegro5/allegro.h>
#include <allegro5/allegro_primitives.h>
#include <allegro5/allegro_font.h>
const char *help =
"HELP:\n"
"LEFT/RIGHT - turn the ship\n"
"UP/DOWN - accelerate/reverse accelerate\n"
"R - reset the simulation\n"
"P - pause/unpause the simulation\n"
"I - show/hide simulation information\n"
"H - show/hide this help information\n"
"F - toggle fullscreen\n"
"Z - zoom in\n"
"SHIFT+Z - zoom out\n"
"Q/ESC - quit";
const char *info_format =
"INFO:\n"
"x: %f\n"
"y: %f\n"
"angle: %f (%f degrees)\n"
"velX: %f px/sec\n"
"velY: %f px/sec";
struct allegro_components {
int primitives_addon;
int font_addon;
ALLEGRO_DISPLAY *display;
int evnt_system;
ALLEGRO_FONT *font;
};
void cleanup_allegro(struct allegro_components *allegro) {
if(allegro->font) {
al_destroy_font(allegro->font);
#ifdef DEBUG
std::cout << "[DEBUG] Destroyed font." << std::endl;
#endif
allegro->font = nullptr;
}
if(allegro->evnt_system) {
evnt_mngr_deinit();
allegro->evnt_system = 0;
}
if(allegro->display) {
al_destroy_display(allegro->display);
#ifdef DEBUG
std::cout << "[DEBUG] Destroyed display." << std::endl;
#endif
allegro->display = nullptr;
}
if(allegro->font_addon) {
al_shutdown_font_addon();
#ifdef DEBUG
std::cout << "[DEBUG] Shutdown font addon." << std::endl;
#endif
allegro->font_addon = 0;
}
if(allegro->primitives_addon) {
al_shutdown_primitives_addon();
#ifdef DEBUG
std::cout << "[DEBUG] Shutdown primitives addon." << std::endl;
#endif
allegro->primitives_addon = 0;
}
}
int main() {
const std::string title = "SpaceShipSim v" + std::string(VERSION);
float zoom = 1.0f;
float display_width = WINDOW_WIDTH;
float display_height = WINDOW_HEIGHT;
struct allegro_components allegro __attribute__((cleanup(cleanup_allegro))) = {
0,
0,
nullptr,
0,
nullptr
};
std::cout << title << std::endl;
if(!al_init()) {
fprintf(stderr, "alleg5: failed to initialize Allegro.\n");
return EXIT_FAILURE;
}
#ifdef DEBUG
std::cout << "[DEBUG] Initialized allegro system." << std::endl;
#endif
if(!(allegro.primitives_addon = al_init_primitives_addon())) {
fprintf(stderr, "alleg5: failed to initialize primitives addon.\n");
return EXIT_FAILURE;
}
#ifdef DEBUG
std::cout << "[DEBUG] Initialized primitives addon." << std::endl;
#endif
if(!(allegro.font_addon = al_init_font_addon())) {
fprintf(stderr, "alleg5: failed to initialize font addon.\n");
return EXIT_FAILURE;
}
#ifdef DEBUG
std::cout << "[DEBUG] Initialized font addon." << std::endl;
#endif
allegro.display = al_create_display(WINDOW_WIDTH, WINDOW_HEIGHT);
if(!allegro.display) {
fprintf(stderr, "alleg5: failed to initialize display.\n");
return EXIT_FAILURE;
}
al_set_window_title(allegro.display, title.c_str());
#ifdef DEBUG
std::cout << "[DEBUG] Created display." << std::endl;
#endif
if(!(allegro.evnt_system = evnt_mngr_init(allegro.display))) {
fprintf(stderr, "alleg5: failed to initialize event queue.\n");
return EXIT_FAILURE;
}
// initialize the spaceship at the center of the screen
Ship ship(400, 300);
// initialize the planet
Planet planet(400.0f, 300.0f, 250.0f);
allegro.font = al_create_builtin_font();
#ifdef DEBUG
std::cout << "[DEBUG] Created font." << std::endl;
#endif
// begin running the simulation
run = 1;
redraw = 1;
show_help = 1;
show_info = 1;
int paused = 0;
int old_paused = 0;
int just_toggled_fullscreen = 0;
int zoom_pressed = 0;
while(run) {
handle_event();
// only redraw or run simulation if the timer event has occurred
if(redraw) {
if(just_toggled_fullscreen) {
display_width = al_get_display_width(allegro.display);
display_height = al_get_display_height(allegro.display);
}
if(paused == old_paused && key_is_down(KEY_PAUSE))
paused = !paused;
else if(paused != old_paused && !key_is_down(KEY_PAUSE))
old_paused = paused;
if(!paused) {
if(key_is_down(KEY_RESET))
ship.reset((float)WINDOW_WIDTH / 2, (float)WINDOW_HEIGHT / 2);
else {
ship.update(planet.getGravity(ship));
}
}
if (key_is_down(KEY_FULLSCREEN) && !just_toggled_fullscreen) {
if(al_get_display_flags(allegro.display) & ALLEGRO_FULLSCREEN_WINDOW)
al_set_display_flag(allegro.display, ALLEGRO_FULLSCREEN_WINDOW, 0);
else
al_set_display_flag(allegro.display, ALLEGRO_FULLSCREEN_WINDOW, 1);
just_toggled_fullscreen = 1;
} else if (!key_is_down(KEY_FULLSCREEN) && just_toggled_fullscreen) {
just_toggled_fullscreen = 0;
}
if(key_is_down(KEY_SHIFT) && key_is_down(KEY_ZOOM) && !zoom_pressed) {
zoom -= ZOOM_STEP;
if(zoom < ZOOM_MIN)
zoom = ZOOM_MIN;
zoom_pressed = 1;
} else if(key_is_down(KEY_ZOOM) && !zoom_pressed) {
zoom += ZOOM_STEP;
if(zoom > ZOOM_MAX)
zoom = ZOOM_MAX;
zoom_pressed = 1;
} else if(!key_is_down(KEY_ZOOM) && zoom_pressed) {
zoom_pressed = 0;
}
al_clear_to_color(al_map_rgb(0, 0, 0));
ALLEGRO_TRANSFORM transform;
al_identity_transform(&transform);
al_scale_transform(&transform, zoom, zoom);
al_translate_transform(&transform,
display_width / 2.0f - ship.getPos().x * zoom,
display_height / 2.0f - ship.getPos().y * zoom);
al_use_transform(&transform);
starfield_draw(ship.getPos().x, ship.getPos().y, zoom,
display_width, display_height);
planet.draw();
ship.draw();
al_identity_transform(&transform);
al_use_transform(&transform);
if(show_info) {
char info[256];
sprintf(info, info_format,
ship.getPos().x, ship.getPos().y,
ship.getDirection(),
RAD_TO_DEG(ship.getDirection()),
ship.getVel().x * FPS, ship.getVel().y * FPS);
al_draw_multiline_text(allegro.font,
al_map_rgb(0xFF, 0xFF, 0xFF),
5, 5, (int)display_width, 10.0f,
ALLEGRO_ALIGN_LEFT,
info);
}
if(show_help) {
al_draw_multiline_text(allegro.font,
al_map_rgb(0xFF, 0xFF, 0xFF),
display_width / 2, display_height / 2 - 50,
(int)display_width, 10.0f,
ALLEGRO_ALIGN_CENTRE,
help);
}
al_flip_display();
redraw = 0;
}
}
return EXIT_SUCCESS;
}
+57
View File
@@ -0,0 +1,57 @@
/*
* Copyright (C) 2026 Ortega Froysa, Nicolás <nicolas@ortegas.org>
* Author: Ortega Froysa, Nicolás <nicolas@ortegas.org>
*
* 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 <http://www.gnu.org/licenses/>.
*/
#include "planet.h"
#include <cmath>
#include <cassert>
#include <allegro5/allegro_primitives.h>
#define GRAVITY_CONSTANT 1.0f // Gravitational constant scaled for simulation
#define SHIP_MASS 1.0f // Assumed constant ship mass
#define MASS_TO_RADIUS 1.5f // Radius scale factor: radius = MASS_TO_RADIUS * mass^(1/3)
Planet::Planet(const float x, const float y, const float mass) :
pos(x, y), mass(mass), radius(MASS_TO_RADIUS * cbrtf(mass))
{}
Vec<float> Planet::getGravity(const Ship &ship) const {
const Vec<float> distance = this->pos - ship.getPos();
if(distance.length() < this->radius)
return Vec<float>(0, 0);
// F = G * m1 * m2 / r^2
const float force = GRAVITY_CONSTANT * SHIP_MASS * this->mass / (distance.length() * distance.length());
// a = F / m_ship = G * m_this / r^2
const float acceleration = force / SHIP_MASS;
// Normalize direction and apply acceleration
return distance.normalized() * acceleration;
}
void Planet::draw() {
// Color intensity based on mass (brighter = more massive)
float color_scale = fminf(1.0f, this->mass / 1000.0f);
int r = (int)(100 + 155 * color_scale);
int g = (int)(100 + 50 * color_scale);
int b = (int)(150 - 100 * color_scale);
al_draw_filled_circle(this->pos.x, this->pos.y, this->radius,
al_map_rgb(r, g, b));
}
+61
View File
@@ -0,0 +1,61 @@
/*
* Copyright (C) 2026 Ortega Froysa, Nicolás <nicolas@ortegas.org>
* Author: Ortega Froysa, Nicolás <nicolas@ortegas.org>
*
* 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 <http://www.gnu.org/licenses/>.
*/
#pragma once
#include "ship.h"
#include "vec.h"
/**
* Function pointer type for calculating planet mass.
* Takes no parameters and returns the mass value.
*/
typedef float (*planet_mass_func)(void);
class Planet {
private:
Vec<float> pos; ///< The x and y coordinates of the planet center.
const float mass; ///< The mass of the planet.
const float radius; ///< The radius of the planet (derived from mass).
public:
/**
* @brief Initialize a planet at a position with a specified mass.
*
* @param x Initial x position of the planet center.
* @param y Initial y position of the planet center.
* @param mass The mass of the planet.
*/
Planet(const float x, const float y, const float mass);
/**
* @brief Calculate the gravitational acceleration on a ship at a given position.
*
* Returns the acceleration vector components due to the planet's gravity.
*
* @param ship Reference to ship.
*
* @returns A Vec<float> representing the gravitational acceleration (ax, ay).
*/
Vec<float> getGravity(const Ship &ship) const;
/**
* @brief Draw the planet.
*/
void draw();
};
+69
View File
@@ -0,0 +1,69 @@
/*
* Copyright (C) 2018,2026 Ortega Froysa, Nicolás <nicolas@ortegas.org>
* Author: Ortega Froysa, Nicolás <nicolas@ortegas.org>
*
* 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 <http://www.gnu.org/licenses/>.
*/
#include "ship.h"
#include "event_manager.h"
#include "globals.h"
#include <cmath>
#include <cassert>
#include <allegro5/allegro_primitives.h>
#define SHIP_RADIUS 10.0f // radius of the ship in pixels
Ship::Ship(const float x, const float y) :
pos(x, y), vel(0, 0), direction(0)
{}
void Ship::update(const Vec<float> &grav) {
if(key_is_down(KEY_RIGHT))
this->direction += TURN_ACCEL;
if(key_is_down(KEY_LEFT))
this->direction -= TURN_ACCEL;
// keep direction within bounds
if(this->direction >= M_PI * 2)
this->direction -= M_PI * 2;
else if(this->direction < 0)
this->direction += M_PI * 2;
if(key_is_down(KEY_UP)) {
this->vel.x += cos(this->direction) * ACCEL;
this->vel.y += sin(this->direction) * ACCEL;
}
if(key_is_down(KEY_DOWN)) {
// moving backwards is slower than moving forward
this->vel.x -= cos(this->direction) * (ACCEL / 2);
this->vel.y -= sin(this->direction) * (ACCEL / 2);
}
// Apply gravitational acceleration
this->vel += grav;
this->pos += this->vel;
}
void Ship::draw() const {
const float x0 = this->pos.x + (cos(this->direction) * SHIP_RADIUS);
const float y0 = this->pos.y + (sin(this->direction) * SHIP_RADIUS);
const float x1 = this->pos.x + (cos(this->direction + M_PI * 0.8f) * SHIP_RADIUS);
const float y1 = this->pos.y + (sin(this->direction + M_PI * 0.8f) * SHIP_RADIUS);
const float x2 = this->pos.x + (cos(this->direction + M_PI * 1.2f) * SHIP_RADIUS);
const float y2 = this->pos.y + (sin(this->direction + M_PI * 1.2f) * SHIP_RADIUS);
al_draw_filled_triangle(x0, y0, x1, y1, x2, y2,
al_map_rgb(0xFF, 0x0, 0x0));
}
+73
View File
@@ -0,0 +1,73 @@
/*
* Copyright (C) 2018,2026 Ortega Froysa, Nicolás <nicolas@ortegas.org>
* Author: Ortega Froysa, Nicolás <nicolas@ortegas.org>
*
* 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 <http://www.gnu.org/licenses/>.
*/
#pragma once
#include "vec.h"
#include <allegro5/allegro.h>
class Ship {
private:
/// Position of the ship in pixels.
Vec<float> pos;
/// Velocity of the ship in pixels per frame.
Vec<float> vel;
/**
* The direction that the ship is facing in radians, where
* 0 is right facing.
*/
float direction;
public:
/**
* @brief Initialize ship.
*
* @param x Initial X position.
* @param y Initial Y position.
*/
Ship(const float x, const float y);
/**
* @brief Updates the ship's variables according to keyboard
* input and gravitational forces.
*
* @param grav Vector of gravitational acceleration in pixels per frame squared.
*/
void update(const Vec<float> &grav);
/**
* @brief Reset ship to position.
*
* @param x X position to reset to.
* @param y Y position to reset to.
*/
inline void reset(float x, float y) {
this->pos.set(x, y);
this->vel.set(0, 0);
this->direction = 0;
}
/**
* @brief Draw the ship.
*/
void draw() const;
inline Vec<float> getPos() const { return pos; }
inline Vec<float> getVel() const { return vel; }
inline float getDirection() const { return direction; }
};
-115
View File
@@ -1,115 +0,0 @@
package spaceshipsim;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
import java.awt.image.*;
import java.util.*;
import spaceshipsim.entities.*;
/**
* @author Nicolás A. Ortega
* @copyright Nicolás A. Ortega
* @license GNU GPLv3
* @year 2014
*
*/
public class SpaceShipSim extends JFrame implements Runnable, KeyListener {
private final String version = "v0.1";
private Thread gameloop;
private BufferedImage backbuffer;
private Graphics2D g2d;
private AffineTransform identity = new AffineTransform();
private Ship ship;
// Constructor:
public SpaceShipSim() {
super("Space Ship Simulator");
setSize(800, 600);
setVisible(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
backbuffer = new BufferedImage(800, 600, BufferedImage.TYPE_INT_RGB);
g2d = backbuffer.createGraphics();
ship = new Ship(400, 300);
addKeyListener(this);
start();
}
public void start() {
gameloop = new Thread(this);
gameloop.start();
}
public void stop() { gameloop = null; }
public void paint(Graphics g) {
g2d.setTransform(identity);
g2d.setPaint(Color.BLACK);
g2d.fillRect(0, 0, getSize().width, getSize().height);
drawInfo();
drawShip();
g.drawImage(backbuffer, 0, 0, this);
}
private void drawInfo() {
g2d.setPaint(Color.WHITE);
g2d.drawString("Welcome to SpaceShipSim " + version, 10, 40);
g2d.drawString("Position: " + (int)ship.getX() + ", " + (int)ship.getY(), 10, 55);
g2d.drawString("Velocity (px/s): " + (int)(ship.getVelX() * 50) + ", " + (int)(ship.getVelY() * 50), 10, 70);
g2d.drawString("Acceleration (px/s/s): " + (int)(ship.getAccelX() * Math.pow(50, 2)) + ", " + (int)(ship.getAccelY() * Math.pow(50, 2)), 10, 85);
g2d.drawString("Move Angle: " + (int)ship.getMoveAngle(), 10, 100);
g2d.drawString("Face Angle: " + (int)(ship.getFaceAngle() - 90), 10, 115);
}
private void drawShip() {
g2d.setTransform(identity);
g2d.translate(ship.getX(), ship.getY());
g2d.rotate(Math.toRadians(ship.getFaceAngle()));
g2d.setColor(Color.RED);
g2d.fill(ship.getShape());
}
public void run() {
Thread t = Thread.currentThread();
while(t == gameloop) {
try {
ship.update();
Thread.sleep(20);
} catch(InterruptedException ie) {
ie.printStackTrace();
}
repaint();
}
}
public void keyPressed(KeyEvent ke) {
//keys[ke.getKeyCode()] = true;
int keyCode = ke.getKeyCode();
if(keyCode == KeyEvent.VK_UP) { ship.setAccelerate(true); }
if(keyCode == KeyEvent.VK_LEFT) { ship.setTurnLeft(true); }
if(keyCode == KeyEvent.VK_RIGHT) { ship.setTurnRight(true); }
}
public void keyReleased(KeyEvent ke) {
int keyCode = ke.getKeyCode();
if(keyCode == KeyEvent.VK_UP) { ship.setAccelerate(false); }
if(keyCode == KeyEvent.VK_LEFT) { ship.setTurnLeft(false); }
if(keyCode == KeyEvent.VK_RIGHT) { ship.setTurnRight(false); }
}
public void keyTyped(KeyEvent ke) {}
public static void main(String[] args) { new SpaceShipSim(); }
}
@@ -1,56 +0,0 @@
package spaceshipsim.entities;
import java.awt.Shape;
/**
* @author Nicolás A. Ortega
* @copyright Nicolás A. Ortega
* @license GNU GPLv3
* @year 2014
*
*/
public class BaseVectorShape {
private Shape shape;
private boolean alive;
private double x, y;
private double velX, velY;
private double moveAngle, faceAngle;
// Constructor:
public BaseVectorShape() {
setShape(null);
setAlive(false);
setX(0.0);
setY(0.0);
setVelX(0.0);
setVelY(0.0);
setMoveAngle(0.0);
setFaceAngle(0.0);
}
// Accessor methods:
public Shape getShape() { return shape; }
public boolean isAlive() { return alive; }
public double getX() { return x; }
public double getY() { return y; }
public double getVelX() { return velX; }
public double getVelY() { return velY; }
public double getMoveAngle() { return moveAngle; }
public double getFaceAngle() { return faceAngle; }
// Setter methods:
public void setShape(Shape shape) { this.shape = shape; }
public void setAlive(boolean alive) { this.alive = alive; }
public void setX(double x) { this.x = x; }
public void incX(double iX) { this.x += iX; }
public void setY(double y) { this.y = y; }
public void incY(double iY) { this.y += iY; }
public void setVelX(double velX) { this.velX = velX; }
public void incVelX(double iVX) { this.velX += iVX; }
public void setVelY(double velY) { this.velY = velY; }
public void incVelY(double iVY) { this.velY += iVY; }
public void setMoveAngle(double nMA) { this.moveAngle = nMA; }
public void incMoveAngle(double iMA) { this.moveAngle += iMA; }
public void setFaceAngle(double nFA) { this.faceAngle = nFA; }
public void incFaceAngle(double iFA) { this.faceAngle += iFA; }
}
-76
View File
@@ -1,76 +0,0 @@
package spaceshipsim.entities;
import java.awt.*;
/**
* @author Nicolás A. Ortega
* @copyright Nicolás A. Ortega
* @license GNU GPLv3
* @year 2014
*
*/
public class Ship extends BaseVectorShape {
// Ship shape points for vector image
private int[] shipx = { -6, -3, 0, 3, 6, 0 };
private int[] shipy = { 6, 7, 7, 7, 6, -7 };
// Booleans for movement
private boolean accelerate = false;
private boolean turnLeft = false;
private boolean turnRight = false;
// Acceleration variables
private double accelerateX;
private double accelerateY;
// Constructor:
public Ship(double nx, double ny) {
setX(nx);
setY(ny);
setShape(new Polygon(shipx, shipy, shipx.length));
setAlive(true);
}
// Update Method:
public void update() {
if(accelerate) {
setMoveAngle(getFaceAngle() - 90);
accelerateX = calcAngleMoveX(getMoveAngle()) * 0.1;
accelerateY = calcAngleMoveY(getMoveAngle()) * 0.1;
incVelX(accelerateX);
incVelY(accelerateY);
} else {
accelerateX = 0;
accelerateY = 0;
}
if(turnLeft) {
incFaceAngle(-5);
if(getFaceAngle() < 0) { setFaceAngle(355); } // 355 = 360 - 5
}
if(turnRight) {
incFaceAngle(5);
if(getFaceAngle() > 360) { setFaceAngle(5); }
}
incX(getVelX());
incY(getVelY());
}
// Accessor methods:
public Rectangle getBounds() {
Rectangle r;
r = new Rectangle((int)getX() - 6, (int)getY() - 6, 12, 12);
return r;
}
public double getAccelX() { return accelerateX; }
public double getAccelY() { return accelerateY; }
// Setter methods:
public void setAccelerate(boolean accel) { this.accelerate = accel; }
public void setTurnLeft(boolean tL) { this.turnLeft = tL; }
public void setTurnRight(boolean tR) { this.turnRight = tR; }
// Methods used for calculations:
public double calcAngleMoveX(double angle) { return (double) (Math.cos(angle * Math.PI / 180)); }
public double calcAngleMoveY(double angle) { return (double) (Math.sin(angle * Math.PI / 180)); }
}
+71
View File
@@ -0,0 +1,71 @@
/*
* Copyright (C) 2026 Ortega Froysa, Nicolás <nicolas@ortegas.org>
* Author: Ortega Froysa, Nicolás <nicolas@ortegas.org>
*
* 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 <http://www.gnu.org/licenses/>.
*/
#include "starfield.h"
#include <stdlib.h>
#include <math.h>
#include <allegro5/allegro.h>
#include <allegro5/allegro_primitives.h>
#define CHUNK_SIZE 256
#define STARS_PER_CHUNK 50
#define STAR_COLOR al_map_rgb(255, 255, 255)
static unsigned int hash_seed(int chunk_x, int chunk_y) {
unsigned int h = 5381;
h = ((h << 5) + h) ^ chunk_x;
h = ((h << 5) + h) ^ chunk_y;
return h;
}
static void generate_chunk_stars(int chunk_x, int chunk_y) {
unsigned int seed = hash_seed(chunk_x, chunk_y);
srand(seed);
float base_x = chunk_x * CHUNK_SIZE;
float base_y = chunk_y * CHUNK_SIZE;
for(int i = 0; i < STARS_PER_CHUNK; ++i) {
float star_x = base_x + (float)(rand() % CHUNK_SIZE);
float star_y = base_y + (float)(rand() % CHUNK_SIZE);
al_draw_pixel(star_x, star_y, STAR_COLOR);
}
}
void starfield_draw(float camera_x, float camera_y, float zoom, float width, float height) {
float view_width = width / zoom;
float view_height = height / zoom;
float left = camera_x - view_width / 2.0f;
float right = camera_x + view_width / 2.0f;
float top = camera_y - view_height / 2.0f;
float bottom = camera_y + view_height / 2.0f;
int chunk_left = (int)floor(left / CHUNK_SIZE);
int chunk_right = (int)floor(right / CHUNK_SIZE);
int chunk_top = (int)floor(top / CHUNK_SIZE);
int chunk_bottom = (int)floor(bottom / CHUNK_SIZE);
for(int cy = chunk_top; cy <= chunk_bottom; ++cy) {
for(int cx = chunk_left; cx <= chunk_right; ++cx) {
generate_chunk_stars(cx, cy);
}
}
}
+38
View File
@@ -0,0 +1,38 @@
/*
* Copyright (C) 2026 Ortega Froysa, Nicolás <nicolas@ortegas.org>
* Author: Ortega Froysa, Nicolás <nicolas@ortegas.org>
*
* 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 <http://www.gnu.org/licenses/>.
*/
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Draw stars in the visible area of the starfield.
*
* @param camera_x The x position of the camera center.
* @param camera_y The y position of the camera center.
* @param zoom The zoom level (scale factor).
* @param width The display width in pixels.
* @param height The display height in pixels.
*/
void starfield_draw(float camera_x, float camera_y, float zoom, float width, float height);
#ifdef __cplusplus
}
#endif
+91
View File
@@ -0,0 +1,91 @@
/*
* Copyright (C) 2026 Ortega Froysa, Nicolás <nicolas@ortegas.org>
* Author: Ortega Froysa, Nicolás <nicolas@ortegas.org>
*
* 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 <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <cmath>
template <typename T>
class Vec {
public:
T x, y;
Vec() : x(0), y(0) {}
Vec(T x, T y) : x(x), y(y) {}
inline void set(T x, T y) {
this->x = x;
this->y = y;
}
inline T length() const {
return std::sqrt(static_cast<double>(x * x + y * y));
}
inline Vec<T> normalized() const {
const T len = length();
if (len == 0)
return Vec<T>(0, 0);
return Vec<T>(x / len, y / len);
}
inline Vec<T>& operator+=(const Vec<T> &other) {
this->x += other.x;
this->y += other.y;
return *this;
}
inline Vec<T>& operator*=(const T scalar) {
this->x *= scalar;
this->y *= scalar;
return *this;
}
inline Vec<T> operator+(const Vec<T> &other) const {
return Vec<T>(this->x + other.x, this->y + other.y);
}
inline Vec<T> operator+(const T scalar) const {
return Vec<T>(this->x + scalar, this->y + scalar);
}
inline Vec<T>& operator-=(const Vec<T> &other) {
this->x -= other.x;
this->y -= other.y;
return *this;
}
inline Vec<T>& operator-=(const T scalar) {
this->x -= scalar;
this->y -= scalar;
return *this;
}
inline Vec<T> operator-(const Vec<T> &other) const {
return Vec<T>(this->x - other.x, this->y - other.y);
}
inline Vec<T> operator-(const T scalar) const {
return Vec<T>(this->x - scalar, this->y - scalar);
}
inline Vec<T> operator*(const T scalar) const {
return Vec<T>(this->x * scalar, this->y * scalar);
}
inline Vec<T> operator/(const T scalar) const {
return Vec<T>(this->x / scalar, this->y / scalar);
}
};