Compare commits

...

47 Commits
v0.2 ... master

Author SHA1 Message Date
Nicolás Ortega Froysa
8924741937
Remove from the TODO 2018-04-13 08:02:55 +02:00
Nicolás Ortega Froysa
63f950e26b
Implement pause functionality. 2018-04-13 08:02:34 +02:00
Nicolás Ortega Froysa
349848ebf6
Remove extra 5.0 stuff (fix later). 2018-04-13 08:01:53 +02:00
Nicolás Ortega Froysa
395c3c854f
Require minimum version of Allegro. 2018-04-04 11:55:02 +02:00
Nicolás Ortega Froysa
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
Nicolás Ortega Froysa
29219bbc2c
Added a TODO list. 2018-03-29 13:04:35 +02:00
Nicolás Ortega Froysa
d343c5e5a0
Move help information further up. 2018-03-29 13:01:09 +02:00
Nicolás Ortega Froysa
17777e2178
No need to update the ship if we reset. 2018-03-29 12:58:37 +02:00
Nicolás Ortega Froysa
609d197227
Better description. 2018-03-29 12:56:01 +02:00
Nicolás Ortega Froysa
e29a0bc7a3
Slower acceleration. 2018-03-29 12:55:48 +02:00
Nicolás Ortega Froysa
92e406bc74
Measure by pixel/second 2018-03-29 11:57:17 +02:00
Nicolás Ortega Froysa
2d64adf476
Put version in window title. 2018-03-29 01:06:15 +02:00
Nicolás Ortega Froysa
ab10fcdf02
Reset simulation feature added. 2018-03-25 18:45:28 +02:00
Nicolás Ortega Froysa
c51f34c888
Fully functional simulation.
I still need to add the restart feature.
2018-03-25 18:43:06 +02:00
Nicolás Ortega Froysa
85435fef8d
Added help information. 2018-03-25 18:24:39 +02:00
Nicolás Ortega Froysa
8e10be3ea9
Forgot to update x and y variables. 2018-03-25 18:02:09 +02:00
Nicolás Ortega Froysa
b41719855a
Set ship turning correctly. 2018-03-25 17:57:37 +02:00
Nicolás Ortega Froysa
008ec2bd72
Added keyboard event source. 2018-03-25 17:57:21 +02:00
Nicolás Ortega Froysa
88f3a5f1a5
Added malfunctioning ship.
Currently it doesn't seem to be detecting the key preses.
2018-03-25 17:47:31 +02:00
Nicolás Ortega Froysa
80113d51ff
Remove global variables.
Global variables are overall bad practice.
2018-03-25 17:14:44 +02:00
Nicolás Ortega Froysa
0faa83c162
Remove help and info from key list. 2018-03-25 17:04:14 +02:00
Nicolás Ortega Froysa
4dc7fbbf04
Create a ship object. 2018-03-25 16:59:03 +02:00
Nicolás Ortega Froysa
a1406c4506
Included debug information. 2018-03-25 16:44:09 +02:00
Nicolás Ortega Froysa
86159b0b69
Initialize the primitives addon. 2018-03-25 16:42:00 +02:00
Nicolás Ortega Froysa
fb023194e3
Add fast-math optimization for release builds. 2018-03-25 16:40:56 +02:00
Nicolás Ortega Froysa
5cefcd8554
Added section of v0.3. 2018-03-25 15:46:46 +02:00
Nicolás Ortega Froysa
fa9a35444b
Invalid keycodes also return 0 (but print a msg in DEBUG). 2018-03-25 15:34:53 +02:00
Nicolás Ortega Froysa
d871bcec41
Implemented key_is_down() function. 2018-03-25 15:29:48 +02:00
Nicolás Ortega Froysa
ea4f4a97b6
Keyboard input added. 2018-03-25 15:22:43 +02:00
Nicolás Ortega Froysa
d57da20ec7
Created an event manager. 2018-03-25 14:53:40 +02:00
Nicolás Ortega Froysa
b99e33fe52
A changelog file of previous releases. 2018-03-25 14:53:08 +02:00
Nicolás Ortega Froysa
768f80a362
Create a display. 2018-03-25 14:27:10 +02:00
Nicolás Ortega Froysa
8c19b96bb7
New install target. 2018-03-25 12:30:39 +02:00
Nicolás Ortega Froysa
1cdd5964f0
First steps. 2018-03-25 12:08:19 +02:00
Nicolás A. Ortega
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
18 changed files with 698 additions and 388 deletions

8
.gitignore vendored
View File

@ -1,5 +1,3 @@
# Ignore binary files
bin/*
# Just in case some .class files escape:
*.class
# Ignore build files
build/*
!build/.keep

10
CHANGELOG Normal file
View File

@ -0,0 +1,10 @@
v0.1: First Release
- Basic simulation.
- Information printing.
v0.2: Menu Bar
- Added a menu bar.
- Can reset the simulation.
v0.3: Port to C
- Codebase ported to C for better performance.

68
CMakeLists.txt Normal file
View File

@ -0,0 +1,68 @@
# Copyright (C) 2018 Ortega Froysa, Nicolás <nortega@themusicinnoise.net>
# Author: Ortega Froysa, Nicolás <nortega@themusicinnoise.net>
#
# 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 2.8)
project(SpaceShipSim C)
set(TARGET_NAME "spaceshipsim")
set(TARGET_VERSION "0.3")
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")
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.c
src/ship.c)
add_definitions(-DVERSION="${TARGET_VERSION}")
if(${CMAKE_BUILD_TYPE} STREQUAL "debug" OR
${CMAKE_BUILD_TYPE} STREQUAL "relwithdebinfo")
add_definitions(-DDEBUG)
else()
add_definitions(-DNDEBUG)
endif()
add_executable(${TARGET_NAME} ${SRCS})
target_link_libraries(${TARGET_NAME}
m # math library
${ALLEG5_LIBRARIES}
${ALLEG5-PRIM_LIBRARIES}
${ALLEG5-FONT_LIBRARIES})
install(TARGETS ${TARGET_NAME}
RUNTIME DESTINATION bin/
CONFIGURATIONS release minsizerel)

39
README Normal file
View File

@ -0,0 +1,39 @@
====================
*** SpaceShipSim ***
====================
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.
# Compiling
-----------
In order to build this program you will require the following dependencies:
- GNU GCC (https://gcc.gnu.org/)
- CMake (https://cmake.org/)
- Allegro 5 (http://liballeg.org/)
You can then compile the program via the following commands:
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: <nortega@themusicinnoise.net>.
# 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 `LICENSE' file for more information).

View File

@ -1,10 +0,0 @@
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.
To compile the source-code, go into the project src/ folder and run the following command:<br>
<code>$ javac spaceshipsim/SpaceShipSim.java</code>
<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!

3
TODO Normal file
View File

@ -0,0 +1,3 @@
TODO:
- Add a fullscreen mode.
- Add presets with stellar masses (for gravity simulation).

0
build/.keep Normal file
View File

144
src/event_manager.c Normal file
View File

@ -0,0 +1,144 @@
/*
* Copyright (C) 2018 Ortega Froysa, Nicolás <nortega@themusicinnoise.net>
* Author: Ortega Froysa, Nicolás <nortega@themusicinnoise.net>
*
* 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;
static ALLEGRO_TIMER *timer;
static int keys[KEY_MAX];
int evnt_mngr_init(ALLEGRO_DISPLAY *display) {
assert(display);
if(!al_install_keyboard())
return 0;
#ifdef DEBUG
puts("Initialized keyboard.");
#endif
timer = al_create_timer(1.0f / FPS);
if(!timer)
return 0;
#ifdef DEBUG
puts("Initialized timer.");
#endif
event_queue = al_create_event_queue();
if(!event_queue)
{
al_destroy_timer(timer);
return 0;
}
#ifdef DEBUG
puts("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() {
al_destroy_timer(timer);
#ifdef DEBUG
puts("Destroyed timer.");
#endif
al_destroy_event_queue(event_queue);
#ifdef DEBUG
puts("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;
default:
break;
}
}
void handle_event() {
ALLEGRO_EVENT evnt;
al_wait_for_event(event_queue, &evnt);
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;
}
}
int key_is_down(int code) {
assert(code >= 0 && code <= KEY_MAX);
return keys[code];
}

62
src/event_manager.h Normal file
View File

@ -0,0 +1,62 @@
/*
* Copyright (C) 2018 Ortega Froysa, Nicolás <nortega@themusicinnoise.net>
* Author: Ortega Froysa, Nicolás <nortega@themusicinnoise.net>
*
* 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>
enum {
KEY_UP = 0x0,
KEY_DOWN = 0x1,
KEY_LEFT = 0x2,
KEY_RIGHT = 0x3,
KEY_RESET = 0x4,
KEY_FULLSCREEN = 0x5,
KEY_PAUSE = 0x6,
KEY_MAX = 0x7
};
/**
* @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);

54
src/globals.h Normal file
View File

@ -0,0 +1,54 @@
/*
* Copyright (C) 2018 Ortega Froysa, Nicolás <nortega@themusicinnoise.net>
* Author: Ortega Froysa, Nicolás <nortega@themusicinnoise.net>
*
* 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
#ifndef VERSION
# define VERSION "[version]"
#endif
#ifndef FPS
# define FPS 60.0f
#endif
#ifndef ACCEL
# define ACCEL 0.1f
#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
#include <math.h>
#ifndef M_PI
# define M_PI 3.14159265f
#endif
#define RAD_TO_DEG(x) (x * 180 / M_PI)
#include <allegro5/allegro.h>
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.

176
src/main.c Normal file
View File

@ -0,0 +1,176 @@
/*
* Copyright (C) 2018 Ortega Froysa, Nicolás <nortega@themusicinnoise.net>
* Author: Ortega Froysa, Nicolás <nortega@themusicinnoise.net>
*
* 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"
int run;
int redraw;
int show_help;
int show_info;
#include <stdio.h>
#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"
"I - show/hide simulation information\n"
"H - show/hide this help information\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";
int main() {
char title[32];
sprintf(title, "SpaceShipSim v%s", VERSION);
puts(title);
if(!al_init())
{
fprintf(stderr, "alleg5: failed to initialize Allegro.\n");
return 1;
}
#ifdef DEBUG
puts("Initialized allegro system.");
#endif
if(!al_init_primitives_addon())
{
fprintf(stderr, "alleg5: failed to initialize primitives addon.\n");
return 1;
}
#ifdef DEBUG
puts("Initialized primitives addon.");
#endif
if(!al_init_font_addon())
{
fprintf(stderr, "alleg5: failed to initialize font addon.\n");
return 1;
}
ALLEGRO_DISPLAY *display = al_create_display(WINDOW_WIDTH, WINDOW_HEIGHT);
if(!display)
{
fprintf(stderr, "alleg5: failed to initialize display.\n");
return 1;
}
al_set_window_title(display, title);
#ifdef DEBUG
puts("Created display.");
#endif
if(!evnt_mngr_init(display))
{
fprintf(stderr, "alleg5: failed to initialize event queue.\n");
al_destroy_display(display);
return 1;
}
// initialize the spaceship at the center of the screen
struct ship ship;
ship_init(&ship, 400, 300);
ALLEGRO_FONT *font = al_create_builtin_font();
// begin running the simulation
run = 1;
redraw = 1;
show_help = 1;
show_info = 1;
int paused = 0;
int old_paused = 0;
while(run)
{
handle_event();
// only redraw or run simulation if the timer event has occurred
if(redraw)
{
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_init(&ship, WINDOW_WIDTH / 2, WINDOW_HEIGHT / 2);
else
ship_update(&ship);
}
al_clear_to_color(al_map_rgb(0, 0, 0));
ship_draw(&ship);
if(show_info)
{
char info[256];
sprintf(info, info_format,
ship.x, ship.y,
ship.direction,
RAD_TO_DEG(ship.direction),
ship.velX * FPS, ship.velY * FPS);
al_draw_multiline_text(font,
al_map_rgb(0xFF, 0xFF, 0xFF),
5, 5, WINDOW_WIDTH, 10.0f,
ALLEGRO_ALIGN_LEFT,
info);
}
if(show_help)
{
al_draw_multiline_text(font,
al_map_rgb(0xFF, 0xFF, 0xFF),
WINDOW_WIDTH / 2, WINDOW_HEIGHT / 2 - 50,
WINDOW_WIDTH, 10.0f,
ALLEGRO_ALIGN_CENTRE,
help);
}
al_flip_display();
redraw = 0;
}
}
al_destroy_font(font);
evnt_mngr_deinit();
al_destroy_display(display);
#ifdef DEBUG
puts("Destroyed display.");
#endif
al_shutdown_font_addon();
#ifdef DEBUG
puts("Shutdown font addon.");
#endif
al_shutdown_primitives_addon();
#ifdef DEBUG
puts("Shutdown primitives addon.");
#endif
return 0;
}

84
src/ship.c Normal file
View File

@ -0,0 +1,84 @@
/*
* Copyright (C) 2018 Ortega Froysa, Nicolás <nortega@themusicinnoise.net>
* Author: Ortega Froysa, Nicolás <nortega@themusicinnoise.net>
*
* 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 <math.h>
#include <assert.h>
#include <allegro5/allegro_primitives.h>
#include <stdio.h>
#define SHIP_RADIUS 10.0f // radius of the ship in pixels
void ship_init(struct ship *ship, int x, int y) {
assert(ship);
ship->x = x;
ship->y = y;
ship->velX = ship->velY = 0;
ship->direction = 0;
}
void ship_update(struct ship *ship) {
assert(ship);
if(key_is_down(KEY_RIGHT))
ship->direction += TURN_ACCEL;
if(key_is_down(KEY_LEFT))
ship->direction -= TURN_ACCEL;
// keep direction within bounds
if(ship->direction >= M_PI * 2)
ship->direction -= M_PI * 2;
else if(ship->direction < 0)
ship->direction += M_PI * 2;
if(key_is_down(KEY_UP))
{
ship->velX += cos(ship->direction) * ACCEL;
ship->velY += sin(ship->direction) * ACCEL;
}
if(key_is_down(KEY_DOWN))
{
// moving backwards is slower than moving forward
ship->velX -= cos(ship->direction) * (ACCEL / 2);
ship->velY -= sin(ship->direction) * (ACCEL / 2);
}
ship->x += ship->velX;
ship->y += ship->velY;
}
void ship_draw(struct ship *ship) {
assert(ship);
const float x0 = ship->x + (cos(ship->direction) *
SHIP_RADIUS);
const float y0 = ship->y + (sin(ship->direction) *
SHIP_RADIUS);
const float x1 = ship->x + (cos(ship->direction +
M_PI * 0.8f) * SHIP_RADIUS);
const float y1 = ship->y + (sin(ship->direction +
M_PI * 0.8f) * SHIP_RADIUS);
const float x2 = ship->x + (cos(ship->direction +
M_PI * 1.2f) * SHIP_RADIUS);
const float y2 = ship->y + (sin(ship->direction +
M_PI * 1.2f) * SHIP_RADIUS);
al_draw_filled_triangle(x0, y0, x1, y1, x2, y2,
al_map_rgb(0xFF, 0x0, 0x0));
}

55
src/ship.h Normal file
View File

@ -0,0 +1,55 @@
/*
* Copyright (C) 2018 Ortega Froysa, Nicolás <nortega@themusicinnoise.net>
* Author: Ortega Froysa, Nicolás <nortega@themusicinnoise.net>
*
* 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>
struct ship {
float x, y; ///< The x and y coordinates of the ship.
float velX, velY; ///< The x and y velocities of the ship.
/**
* The direction that the ship is facing in radians, where
* 0 is right facing.
*/
float direction;
};
/**
* @brief Initialize the ship at a position.
*
* @param ship A pointer to the ship object.
* @param x Initial x position of the ship.
* @param y Initial y position of the ship.
*/
void ship_init(struct ship *ship, int x, int y);
/**
* @brief Updates the ship's variables according to keyboard
* input.
*
* @param ship A pointer to the ship object.
*/
void ship_update(struct ship *ship);
/**
* @brief Draw the ship.
*
* @param ship Ship object to draw.
*/
void ship_draw(struct ship *ship);

View File

@ -1,106 +0,0 @@
package spaceshipsim;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
import java.util.*;
import spaceshipsim.entities.*;
/**
* @author Nicolás A. Ortega
* @copyright Nicolás A. Ortega
* @license GNU GPLv3
* @year 2014
*
*/
public class SimPanel extends JPanel implements Runnable, KeyListener {
// Graphics/Framework items
private Thread gameloop;
//private BufferedImage backbuffer;
private Graphics2D g2d;
//private AffineTransform identity = new AffineTransform();
// The Ship
private Ship ship;
public SimPanel() {
setFocusable(true);
ship = new Ship(400, 300);
addKeyListener(this);
start();
}
public void start() {
gameloop = new Thread(this);
gameloop.start();
}
public void stop() { gameloop = null; }
public void paintComponent(Graphics g) {
super.paintComponent(g);
g2d = (Graphics2D) g;
g2d.setColor(Color.BLACK);
g2d.fillRect(0, 0, 800, 600);
drawInfo();
drawShip();
}
private void drawInfo() {
g2d.translate(0, 10);
g2d.setColor(Color.WHITE);
g2d.drawString("Welcome to SpaceShipSim v0.2", 10, 10);
g2d.drawString("Position: " + (int)ship.getX() + ", " + (int)ship.getY(), 10, 25);
g2d.drawString("Velocity (px/s): " + (int)(ship.getVelX() * 50) + ", " + (int)(ship.getVelY() * 50), 10, 40);
g2d.drawString("Acceleration (px/s/s): " + (int)(ship.getAccelX() * Math.pow(50, 2)) + ", " + (int)(ship.getAccelY() * Math.pow(50, 2)), 10, 55);
g2d.drawString("Move Angle: " + (int)ship.getMoveAngle(), 10, 70);
g2d.drawString("Face Angle: " + (int)(ship.getFaceAngle() - 90), 10, 85);
}
private void drawShip() {
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) {
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 void reset() {
ship = new Ship(400, 300);
}
}

View File

@ -1,119 +0,0 @@
package spaceshipsim;
import javax.swing.*;
import java.awt.event.*;
/**
* @author Nicolás A. Ortega
* @copyright Nicolás A. Ortega
* @license GNU GPLv3
* @year 2014
*
*/
public class SpaceShipSim {
private JFrame frame;
private SimPanel panel;
// Menu items
JMenuBar menuBar;
JMenu simulationMenu;
JMenuItem resetItem;
JMenuItem exitItem;
JMenu helpMenu;
JMenuItem instructionsItem;
JMenuItem licenseItem;
JMenuItem aboutItem;
// Constructor:
public SpaceShipSim() {
frame = new JFrame("SpaceShipSim");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
panel = new SimPanel();
frame.add(panel);
menuSetup();
frame.setSize(800, 600);
frame.setVisible(true);
}
public void menuSetup() {
menuBar = new JMenuBar();
simulationMenu = new JMenu("Simulation");
resetItem = new JMenuItem("Reset");
exitItem = new JMenuItem("Exit");
helpMenu = new JMenu("Help");
instructionsItem = new JMenuItem("Instructions");
licenseItem = new JMenuItem("License");
aboutItem = new JMenuItem("About");
resetItem.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent ae) { panel.reset(); }
});
exitItem.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent ae) {
panel.stop();
System.exit(0);
}
});
instructionsItem.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent ae) {
new Window("Instructions", "Accelerate: Up Arrow\n" +
"Turn left: Left Arrow\n" +
"Turn right: Right Arrow\n\n");
}
});
licenseItem.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent ae) {
new Window("License Information",
"SpaceShipSim v0.2, a simulation of a spaceship in a frictionless environment\n" +
"Copyright (C) 2014 Nicolás A. Ortega\n\n" +
"This program is free software: you can redistribute it and/or modify\n" +
"it under the terms of the GNU General Public License as published by\n" +
"the Free Software Foundation, either version 3 of the License, or\n" +
"(at your option) any later version.\n\n" +
"This program is distributed in the hope that it will be useful,\n" +
"but WITHOUT ANY WARRANTY; without even the implied warranty of\n" +
"MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" +
"GNU General Public License for more details.\n\n" +
"You should have received a copy of the GNU General Public License\n" +
"along with this program. If not, see <http://www.gnu.org/licenses/>.\n\n");
}
});
aboutItem.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent ae) {
new Window("About", "SpaceShipSim v0.2\n" +
"Copyright (C) 2014 Nicolás A. Ortega\n" +
"Contact: nicolas.ortega.froysa@gmail.com\n" +
"Source-code: https://github.com/Deathsbreed/SpaceShipSim\n" +
"Developers: Nicolás Ortega\n\n");
}
});
resetItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_R, InputEvent.CTRL_MASK));
exitItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Q, InputEvent.CTRL_MASK));
simulationMenu.add(resetItem);
simulationMenu.addSeparator();
simulationMenu.add(exitItem);
helpMenu.add(instructionsItem);
helpMenu.add(licenseItem);
helpMenu.addSeparator();
helpMenu.add(aboutItem);
menuBar.add(simulationMenu);
menuBar.add(helpMenu);
frame.setJMenuBar(menuBar);
}
public static void main(String[] args) { new SpaceShipSim(); }
}

View File

@ -1,16 +0,0 @@
package spaceshipsim;
import javax.swing.*;
/**
* @author Nicolás A. Ortega
* @copyright Nicolás A. Ortega
* @license GNU GPLv3
* @year 2014
*
*/
public class Window {
public Window(String title, String infoMessage) {
JOptionPane.showMessageDialog(null, infoMessage, title, JOptionPane.INFORMATION_MESSAGE);
}
}

View File

@ -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; }
}

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)); }
}