|
|
|
@ -1,14 +1,16 @@
@@ -1,14 +1,16 @@
|
|
|
|
|
#include "game.h" |
|
|
|
|
#include "draw.h" |
|
|
|
|
#include "audio.h" |
|
|
|
|
#include "environment.h" |
|
|
|
|
#include "types.h" |
|
|
|
|
#include <SDL2/SDL_mixer.h> |
|
|
|
|
#include <SDL2/SDL_scancode.h> |
|
|
|
|
#include <SDL2/SDL_timer.h> |
|
|
|
|
#include <SDL2/SDL_ttf.h> |
|
|
|
|
#include <SDL2/SDL_mutex.h> |
|
|
|
|
|
|
|
|
|
#include "game.h" |
|
|
|
|
#include "draw.h" |
|
|
|
|
#include "audio.h" |
|
|
|
|
#include "environment.h" |
|
|
|
|
#include "types.h" |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#define FLOOR_THICKNESS 200 |
|
|
|
|
#define MAX_ROPE_GRAB_LEN 80000 |
|
|
|
|
#define MIN_PHYSICS_STEP 6.0 |
|
|
|
@ -23,6 +25,22 @@ player_st *glob_player;
@@ -23,6 +25,22 @@ player_st *glob_player;
|
|
|
|
|
SDL_Renderer *debug_ren; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* |
|
|
|
|
* File containing main game logic, including physics, input handling, |
|
|
|
|
* and user interface.
|
|
|
|
|
* |
|
|
|
|
* If multithreading is in use everything in this file will be run in the |
|
|
|
|
* physics thread and communicate with the drawing thread (the main thread) |
|
|
|
|
* using shared heap memory.
|
|
|
|
|
* |
|
|
|
|
* At the start of a frame the shared memory is locked |
|
|
|
|
* and copied.
|
|
|
|
|
* |
|
|
|
|
* |
|
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool in_game; |
|
|
|
|
bool game_paused = false; |
|
|
|
|
extern bool mute; |
|
|
|
@ -44,9 +62,6 @@ struct ui_state gameui = {};
@@ -44,9 +62,6 @@ struct ui_state gameui = {};
|
|
|
|
|
struct timespec last_tick; |
|
|
|
|
double time_remaining = 0; |
|
|
|
|
|
|
|
|
|
/* array of all the things in the world and their kinds */ |
|
|
|
|
//world_thing *world;
|
|
|
|
|
|
|
|
|
|
void startgame(SDL_Renderer * ren) ; |
|
|
|
|
|
|
|
|
|
void process_keydown(SDL_Keysym key); |
|
|
|
@ -67,6 +82,12 @@ void ratcheted_winch_motor_update(Motor* motor);
@@ -67,6 +82,12 @@ void ratcheted_winch_motor_update(Motor* motor);
|
|
|
|
|
void winch_motor_update (struct motorstruct *motor);
|
|
|
|
|
void load_level();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* -----------------------------------------------------------------------------
|
|
|
|
|
* User interface |
|
|
|
|
* -----------------------------------------------------------------------------
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
void reset_textbox(struct textbox_info *tb) { |
|
|
|
|
tb->text_input_bufpos = 0; |
|
|
|
|
memset(tb->text_input, 0, sizeof(tb->text_input)); |
|
|
|
@ -111,6 +132,15 @@ void new_level_tb_close_callback(struct textbox_info*textbox, void*callback) {
@@ -111,6 +132,15 @@ void new_level_tb_close_callback(struct textbox_info*textbox, void*callback) {
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* -----------------------------------------------------------------------------
|
|
|
|
|
* Scoring |
|
|
|
|
* -----------------------------------------------------------------------------
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Update the level timer each frame.
|
|
|
|
|
*/ |
|
|
|
|
void level_timer_update(bool reset) { |
|
|
|
|
static int start_point = 0; |
|
|
|
|
long now = SDL_GetTicks(); |
|
|
|
@ -137,6 +167,9 @@ int win_long_comparator(void *context_unused, const void *a, const void *b) {
@@ -137,6 +167,9 @@ int win_long_comparator(void *context_unused, const void *a, const void *b) {
|
|
|
|
|
return A - B; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Sort the 'highscores' |
|
|
|
|
*/ |
|
|
|
|
void sort_times(void) { |
|
|
|
|
#ifdef __linux__ |
|
|
|
|
qsort_r(save_times_lst.times, save_times_lst.size, sizeof(long), long_comparator, NULL); |
|
|
|
@ -153,6 +186,12 @@ long get_best_time(void) {
@@ -153,6 +186,12 @@ long get_best_time(void) {
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Read and parse highschores list from disk.
|
|
|
|
|
* |
|
|
|
|
* Will panic if the folder does not exist. |
|
|
|
|
* |
|
|
|
|
*/ |
|
|
|
|
int load_score_times(char *filename) { |
|
|
|
|
|
|
|
|
|
char *fn; |
|
|
|
@ -218,6 +257,11 @@ int load_score_times(char *filename) {
@@ -218,6 +257,11 @@ int load_score_times(char *filename) {
|
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* |
|
|
|
|
* Dynamically add a recorded run time to the list of saved times. |
|
|
|
|
* |
|
|
|
|
*/ |
|
|
|
|
int add_time(long time) { |
|
|
|
|
if (save_times_lst.capacity == save_times_lst.size + 5) { |
|
|
|
|
long newcap = save_times_lst.capacity * 2; |
|
|
|
@ -230,6 +274,9 @@ int add_time(long time) {
@@ -230,6 +274,9 @@ int add_time(long time) {
|
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Write out the saved times list.
|
|
|
|
|
*/ |
|
|
|
|
int write_times(void) { |
|
|
|
|
FILE *f = fopen(save_times_lst.filename, "w"); |
|
|
|
|
if (!f) { |
|
|
|
@ -244,9 +291,38 @@ int write_times(void) {
@@ -244,9 +291,38 @@ int write_times(void) {
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* ----------------------------------------------------------------------------
|
|
|
|
|
* Physics
|
|
|
|
|
* ---------------------------------------------------------------------------- |
|
|
|
|
* |
|
|
|
|
* Simple point-mass based physics system. Physics objects are called `Body`s.
|
|
|
|
|
* |
|
|
|
|
* Position is calculated by integrating acceleration and velocity, using a |
|
|
|
|
* fixed timestep that is detached from the framerate. Each frame it completes |
|
|
|
|
* as many physics steps as neccessary to catch up to the current time.
|
|
|
|
|
*
|
|
|
|
|
* Player interactions use forces generated by the 'motor' |
|
|
|
|
* datastructures and functions. Motors can apply a force at a given 'rate': |
|
|
|
|
* they accelerate a body to a maximum velocity and do nothing over that |
|
|
|
|
* velocity. It is posisble to update their output at each physics step.
|
|
|
|
|
* |
|
|
|
|
* The grappling hook is controlled by 'string' functions and datastructures, |
|
|
|
|
* which have a parent object (the player) an attachment endpoint position, and |
|
|
|
|
* a motor. Strings can be updated each physics step. |
|
|
|
|
* |
|
|
|
|
* All collisions use convex polygons and the separating axis theorem test. |
|
|
|
|
* They are culled by x-coordinate based on the viewport position, since the |
|
|
|
|
* world is mostly horizontal. |
|
|
|
|
* |
|
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// collision poly size must be 2x shape_size + 1
|
|
|
|
|
/*
|
|
|
|
|
* Update an objects collision poly based on its current position smeared over |
|
|
|
|
* its velocity.
|
|
|
|
|
*/ |
|
|
|
|
void cast_update_collision_poly(Body *body) { |
|
|
|
|
// collision poly size must be 2x shape_size + 1
|
|
|
|
|
for (int i=0; i < body->collision_shape_size; i++) { |
|
|
|
|
double x = body->collision_shape[i].x + body->position.x; |
|
|
|
|
double y = body->collision_shape[i].y + body->position.y; |
|
|
|
@ -263,29 +339,31 @@ void cast_update_collision_poly(Body *body) {
@@ -263,29 +339,31 @@ void cast_update_collision_poly(Body *body) {
|
|
|
|
|
body->collision_poly[k].y = y;
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/*int i=body->collision_shape_size - 1;*/ |
|
|
|
|
/*double x = body->collision_shape[i].x + body->next_position.x;*/ |
|
|
|
|
/*double y = body->collision_shape[i].y + body->next_position.y;*/ |
|
|
|
|
|
|
|
|
|
/*body->collision_poly[body->collision_shape_size - 1 + i].x = x; */ |
|
|
|
|
/*body->collision_poly[body->collision_shape_size - 1 + i].y = y; */ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*body->collision_poly[(body->collision_poly_size - 1) * 2 + 1] = body->collision_poly[(body->collision_poly_size - 1) * 2 + 1];*/ |
|
|
|
|
/*body->collision_poly[(body->collision_poly_size - 1) * 2 + 2] = body->collision_poly[(body->collision_poly_size - 1)];*/ |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Constant motor velocity curve. |
|
|
|
|
*/ |
|
|
|
|
void default_motor_curve(Motor *motor) { |
|
|
|
|
// constant
|
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Get the i'th world item. |
|
|
|
|
*/ |
|
|
|
|
world_thing world_getter(int i) { |
|
|
|
|
world_thing *item = arlst_get(&world.items, i); |
|
|
|
|
return *item; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Random walk to generate the floor based on compiled constant parameters.
|
|
|
|
|
* |
|
|
|
|
* \param extend_down: do the polys extend down or up: true => floor, false => ceiling |
|
|
|
|
* |
|
|
|
|
*/ |
|
|
|
|
FloorPoly* generate_floor_simple(int num_polys, bool extend_down, int st_height) { |
|
|
|
|
FloorPoly *floor = calloc(num_polys, sizeof(FloorPoly)); |
|
|
|
|
Vect last, next; |
|
|
|
@ -333,8 +411,13 @@ FloorPoly* generate_floor_simple(int num_polys, bool extend_down, int st_height)
@@ -333,8 +411,13 @@ FloorPoly* generate_floor_simple(int num_polys, bool extend_down, int st_height)
|
|
|
|
|
return floor; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// @param uninitialised Body pointer
|
|
|
|
|
// @result: malloc and configure a physics thing pointer
|
|
|
|
|
/**
|
|
|
|
|
* Get an empty valid physics object.
|
|
|
|
|
*
|
|
|
|
|
* \param uninitialised Body pointer |
|
|
|
|
* \result: malloc and configure a physics thing pointer |
|
|
|
|
* |
|
|
|
|
*/ |
|
|
|
|
void get_new_physics(Body **phys) { |
|
|
|
|
static int uid = 0; |
|
|
|
|
|
|
|
|
@ -369,16 +452,19 @@ void get_new_physics(Body **phys) {
@@ -369,16 +452,19 @@ void get_new_physics(Body **phys) {
|
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/*void updatePlayerCollision(Body *physics) {*/ |
|
|
|
|
/*physics->collision_poly[0].x = physics->x_pos;*/ |
|
|
|
|
/*physics->collision_poly[0].y = physics->y_pos;*/ |
|
|
|
|
/*}*/ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* noop for static strings. |
|
|
|
|
* |
|
|
|
|
*/ |
|
|
|
|
int string_update_fixed(String *string) { |
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Attach the end point of s string to a position in the world. |
|
|
|
|
* |
|
|
|
|
*/ |
|
|
|
|
int string_set_end(String *string, Vect *setting) { |
|
|
|
|
string->end_point = *setting; |
|
|
|
|
return 0; |
|
|
|
@ -399,8 +485,11 @@ String *get_fixed_strings(int number) {
@@ -399,8 +485,11 @@ String *get_fixed_strings(int number) {
|
|
|
|
|
return strings; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Create a player object with allocated and zeroed physics at the given |
|
|
|
|
* position in the world. |
|
|
|
|
*/ |
|
|
|
|
player_st get_player(int x, int y) { |
|
|
|
|
/* creates player at given postion and zeroes physics */ |
|
|
|
|
|
|
|
|
|
// player
|
|
|
|
|
player_st player; |
|
|
|
@ -459,6 +548,9 @@ player_st get_player(int x, int y) {
@@ -459,6 +548,9 @@ player_st get_player(int x, int y) {
|
|
|
|
|
return (player); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Collision test for two points.
|
|
|
|
|
*/ |
|
|
|
|
bool point_point_colcheck(Vect one, Vect two) { |
|
|
|
|
if (one.x == two.x && one.y == two.y) { |
|
|
|
|
return true; |
|
|
|
@ -471,6 +563,9 @@ typedef struct {
@@ -471,6 +563,9 @@ typedef struct {
|
|
|
|
|
Vect two; |
|
|
|
|
} Collision; |
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Collision test for a point and line. |
|
|
|
|
*/ |
|
|
|
|
bool point_line_colcheck(Vect line[2], Vect point) { |
|
|
|
|
// point is outside the rectangle made by the line
|
|
|
|
|
if ((point.x > line[0].x && point.x > line[1].x) |
|
|
|
@ -494,15 +589,17 @@ bool point_line_colcheck(Vect line[2], Vect point) {
@@ -494,15 +589,17 @@ bool point_line_colcheck(Vect line[2], Vect point) {
|
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Projects a body's collision polygon at the origin onto the line through the
|
|
|
|
|
* origin described by V. |
|
|
|
|
* |
|
|
|
|
*/ |
|
|
|
|
double *project_col_poly(Body *shape, Vect V) { |
|
|
|
|
double *proj = calloc(shape->collision_poly_size, sizeof(double)); |
|
|
|
|
for (int i = 0; i < shape->collision_poly_size; i++) { |
|
|
|
|
Vect point; |
|
|
|
|
point.x = shape->collision_poly[i].x; |
|
|
|
|
point.y = shape->collision_poly[i].y; |
|
|
|
|
//double mag = vect_mag(point);
|
|
|
|
|
// printf("point: %f %f mag: %f\n", point.x, point.y, vect_mag(point));
|
|
|
|
|
// printf("Vectp: %f %f mag: %f\n", V.x, V.y, vect_mag(V));
|
|
|
|
|
proj[i] = vect_scalar_projection(point, V); |
|
|
|
|
} |
|
|
|
|
double min, max; |
|
|
|
@ -524,6 +621,9 @@ double *project_col_poly(Body *shape, Vect V) {
@@ -524,6 +621,9 @@ double *project_col_poly(Body *shape, Vect V) {
|
|
|
|
|
return res; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Get the normal of the line described by the start and end points. |
|
|
|
|
*/ |
|
|
|
|
Vect get_normal(Vect start, Vect end) { |
|
|
|
|
Vect norm; |
|
|
|
|
double x = (end.x - start.x); |
|
|
|
@ -537,13 +637,35 @@ Vect get_normal(Vect start, Vect end) {
@@ -537,13 +637,35 @@ Vect get_normal(Vect start, Vect end) {
|
|
|
|
|
return norm; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Collision test for two convex polygons.
|
|
|
|
|
* |
|
|
|
|
* Uses the separating axis theorem test.
|
|
|
|
|
* |
|
|
|
|
* P: IFF two convex polygons are intersecting, there will exist a line running |
|
|
|
|
* between them that intersects neither.
|
|
|
|
|
* |
|
|
|
|
* Corrolary: IFF two convex polygons are intersecting, there will be an edge |
|
|
|
|
* of one of them where if you extend it and project both shapes onto it, the |
|
|
|
|
* shapes will overlap. |
|
|
|
|
*
|
|
|
|
|
* Corrolary: Finding all these overlaps and taking the minimum gives the |
|
|
|
|
* minimum vector to take the shapes out of intersection. |
|
|
|
|
* |
|
|
|
|
* \param one: first body |
|
|
|
|
* \param two: second body
|
|
|
|
|
* \param translation: The minimum vector to take `one` and `two` out of intersection. |
|
|
|
|
* \return: they are intersecting |
|
|
|
|
* |
|
|
|
|
*/ |
|
|
|
|
bool sat_collision_check(Body *one, Body *two, Vect *translation) { |
|
|
|
|
// reference:
|
|
|
|
|
// http://www.dyn4j.org/2010/01/sat/#sat-inter
|
|
|
|
|
//
|
|
|
|
|
// TODO: Maybe avoid calculating the centre of the boxes; have body->position
|
|
|
|
|
// be the centre and translate the collision box to be around that. It does
|
|
|
|
|
// make placing a little more complex but no bother.
|
|
|
|
|
bool sat_collision_check(Body *one, Body *two, Vect *translation) { |
|
|
|
|
|
|
|
|
|
int num_axes = one->collision_poly_size + two->collision_poly_size; |
|
|
|
|
Vect *axes = calloc(num_axes, sizeof(Vect)); |
|
|
|
|
|
|
|
|
@ -637,17 +759,12 @@ bool sat_collision_check(Body *one, Body *two, Vect *translation) {
@@ -637,17 +759,12 @@ bool sat_collision_check(Body *one, Body *two, Vect *translation) {
|
|
|
|
|
two_position.x /= two->collision_poly_size; |
|
|
|
|
two_position.y /= two->collision_poly_size; |
|
|
|
|
|
|
|
|
|
/*printf("ONE POS: %f %f", one_position.x, one_position.y);*/ |
|
|
|
|
/*printf("TWO POS: %f %f", two_position.x, one_position.y);*/ |
|
|
|
|
|
|
|
|
|
direction.x = one_position.x - two_position.x; |
|
|
|
|
direction.y = one_position.y - two_position.y; |
|
|
|
|
|
|
|
|
|
double dot = vect_scalar_projection(trans, direction); |
|
|
|
|
|
|
|
|
|
/*printf("DIRECTION: %f %f\n\n", direction.x, direction.y);*/ |
|
|
|
|
/*printf("DOT: %f\n\n", dot);*/ |
|
|
|
|
|
|
|
|
|
if (dot > 0) { |
|
|
|
|
trans = vect_scalar(trans, -1); |
|
|
|
|
} |
|
|
|
@ -662,6 +779,16 @@ bool sat_collision_check(Body *one, Body *two, Vect *translation) {
@@ -662,6 +779,16 @@ bool sat_collision_check(Body *one, Body *two, Vect *translation) {
|
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Check collision between two bodies using an appropriate scheme.
|
|
|
|
|
* |
|
|
|
|
* |
|
|
|
|
* \param one: first body |
|
|
|
|
* \param two: second body
|
|
|
|
|
* \param translation: The minimum vector to take `one` and `two` out of intersection. |
|
|
|
|
* \return: they are intersecting |
|
|
|
|
* |
|
|
|
|
*/ |
|
|
|
|
bool check_collision(Body *one, Body *two, Vect *translation) { |
|
|
|
|
int onesize = one->collision_poly_size; |
|
|
|
|
int twosize = two->collision_poly_size; |
|
|
|
@ -766,7 +893,6 @@ void load_level() {
@@ -766,7 +893,6 @@ void load_level() {
|
|
|
|
|
|
|
|
|
|
destroy_physics_collection(&world.uniques_index[ROOM_W]->room->ceil); |
|
|
|
|
destroy_physics_collection(&world.uniques_index[ROOM_W]->room->floor); |
|
|
|
|
//destroy_environment(&world.uniques_index[ROOM_W]->room->env);
|
|
|
|
|
|
|
|
|
|
get_floor_ceiling(); |
|
|
|
|
draw_watch.best_time = get_best_time(); |
|
|
|
@ -1263,7 +1389,10 @@ bool get_motor_active(Body *thing, int i) {
@@ -1263,7 +1389,10 @@ bool get_motor_active(Body *thing, int i) {
|
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* Basic physics works by adding up the acceleratino caused by all the forces on
|
|
|
|
|
/*
|
|
|
|
|
* Update the physics state for a body. |
|
|
|
|
* |
|
|
|
|
* Basic physics works by adding up the acceleration caused by all the forces on |
|
|
|
|
* the object, converting it to velocity, then doing collision detection and
|
|
|
|
|
* applying various reactive forces (friction etc) and finally adjusting the
|
|
|
|
|
* object's position.
|
|
|
|
@ -1288,11 +1417,6 @@ void advance_thing(Body * thing) {
@@ -1288,11 +1417,6 @@ void advance_thing(Body * thing) {
|
|
|
|
|
|
|
|
|
|
// collisions
|
|
|
|
|
if ((numcols = process_collisions(thing, &translation))) { |
|
|
|
|
/*double check = vect_scalar_projection(translation, thing->vel);*/ |
|
|
|
|
/*if (check >= 0) {*/ |
|
|
|
|
/*translation.x *= -1;*/ |
|
|
|
|
/*translation.y *= -1;*/ |
|
|
|
|
/*}*/ |
|
|
|
|
|
|
|
|
|
// correct position using translation vector.
|
|
|
|
|
thing->next_position.x += translation.x; |
|
|
|
@ -1345,33 +1469,6 @@ void advance_thing(Body * thing) {
@@ -1345,33 +1469,6 @@ void advance_thing(Body * thing) {
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/*double norm = 9.81 * thing->obj_mass;*/ |
|
|
|
|
/*Vect x;*/ |
|
|
|
|
/*x.y = 0; x.x = 1;*/ |
|
|
|
|
/*if (vect_scalar_projection(thing->vel, translation) > 0) {*/ |
|
|
|
|
/*friction.x = translation.y;*/ |
|
|
|
|
/*friction.y = -translation.x;*/ |
|
|
|
|
/*} else {*/ |
|
|
|
|
/*friction.x = -translation.y;*/ |
|
|
|
|
/*friction.y = translation.x;*/ |
|
|
|
|
/*}*/ |
|
|
|
|
|
|
|
|
|
// force
|
|
|
|
|
/*friction.x = friction.x * norm * fric_const;*/ |
|
|
|
|
/*friction.y = friction.y * norm * fric_const;*/ |
|
|
|
|
// printf("friction accel: %e %e\n", friction.x, friction.y);
|
|
|
|
|
// printf("velocity: %e %e\n", thing->vel.x, thing->vel.y);
|
|
|
|
|
|
|
|
|
|
/*set_motor_newtons(thing, M_FRICTION, friction.x, friction.y);*/ |
|
|
|
|
/*set_motor_max_velocity(thing, M_FRICTION, vect_mag(project_vect(thing->vel, friction)));*/ |
|
|
|
|
|
|
|
|
|
// restitution force
|
|
|
|
|
/*rest.x = 0;*/ |
|
|
|
|
/*rest.y = 0;*/ |
|
|
|
|
/*double impulse = thing->obj_mass * vect_mag(thing->vel) * thing->obj_elasticity;*/ |
|
|
|
|
/*rest.x = cos(vect_dir(translation)) * impulse;*/ |
|
|
|
|
/*rest.y = sin(vect_dir(translation)) * impulse;*/ |
|
|
|
|
/*accel_thing(thing, rest.x, rest.y);*/ |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// pendulums
|
|
|
|
@ -1444,21 +1541,6 @@ void advance_thing(Body * thing) {
@@ -1444,21 +1541,6 @@ void advance_thing(Body * thing) {
|
|
|
|
|
|
|
|
|
|
double velocity = sqrt((double)(thing->vel.x * thing->vel.x + thing->vel.y * thing->vel.y)); |
|
|
|
|
|
|
|
|
|
// simple air drag
|
|
|
|
|
|
|
|
|
|
/*if (velocity > 0.000000000000000) {*/ |
|
|
|
|
/*double dir = atan2((double)thing->y_vel, (double)thing->x_vel) + M_PI;*/ |
|
|
|
|
|
|
|
|
|
/*double absolute_force = 5 * thing->obj_mass * (velocity / time_delta); // 2 * 0.1231 * 5;*/ |
|
|
|
|
/*printf("dir %e %e\n\n", dir, dir - M_PI);*/ |
|
|
|
|
/*printf("force %e\n\n", absolute_force);*/ |
|
|
|
|
|
|
|
|
|
/*double f_x = (cos(dir)) * absolute_force;*/ |
|
|
|
|
/*double f_y = (sin(dir)) * absolute_force;*/ |
|
|
|
|
|
|
|
|
|
/*accel_thing(thing, (float)f_x, (float)f_y);*/ |
|
|
|
|
|
|
|
|
|
/*}*/ |
|
|
|
|
|
|
|
|
|
if (fabsl((*thing).vel.x) < 0.001) { |
|
|
|
|
(*thing).vel.x = 0;
|
|
|
|
@ -1489,13 +1571,6 @@ void advance_thing(Body * thing) {
@@ -1489,13 +1571,6 @@ void advance_thing(Body * thing) {
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/*void destroy_projectile(Projectile** proj) {*/ |
|
|
|
|
/*for (int i = 0; i < things_in_world; i ++) {*/ |
|
|
|
|
/*if (world[i].projectile == *proj) {*/ |
|
|
|
|
|
|
|
|
|
/*}*/ |
|
|
|
|
/*}*/ |
|
|
|
|
/*}*/ |
|
|
|
|
|
|
|
|
|
void *default_projectile_step(struct Projectile *self) { |
|
|
|
|
advance_thing(self->physics); |
|
|
|
@ -1542,16 +1617,8 @@ void advance_things(void) {
@@ -1542,16 +1617,8 @@ void advance_things(void) {
|
|
|
|
|
continue; |
|
|
|
|
case FLOOR: |
|
|
|
|
continue; |
|
|
|
|
/*for (int k = 0; k < world.get(i).floor->numPolys; k++) {*/ |
|
|
|
|
/*advance_thing(world.get(i).floor->polys[k].physics);*/ |
|
|
|
|
/*}*/ |
|
|
|
|
/*break;*/ |
|
|
|
|
case CEILING: |
|
|
|
|
continue; |
|
|
|
|
/*for (int k = 0; k < world.get(i).floor->numPolys; k++) {*/ |
|
|
|
|
/*advance_thing(world.get(i).floor->polys[k].physics);*/ |
|
|
|
|
/*}*/ |
|
|
|
|
/*break;*/ |
|
|
|
|
case PROJECTILE: |
|
|
|
|
if ((numcols = process_collisions(world.get(i).projectile->physics, |
|
|
|
|
&translation))) { |
|
|
|
@ -1619,8 +1686,6 @@ void get_room(void) {
@@ -1619,8 +1686,6 @@ void get_room(void) {
|
|
|
|
|
|
|
|
|
|
FloorPoly *ceil = generate_floor_simple(floorsize, false, 1000); |
|
|
|
|
|
|
|
|
|
// printf("floor: %f %f\n", polys[2].left.x, polys[2].left.y);
|
|
|
|
|
// printf("ceil: %f %f\n", ceil[2].left.x, ceil[2].left.y);
|
|
|
|
|
|
|
|
|
|
Floor* ceiling = calloc(1, sizeof(Floor)); |
|
|
|
|
ceiling->polys = ceil; |
|
|
|
@ -1645,6 +1710,11 @@ GlobWorld create_world() {
@@ -1645,6 +1710,11 @@ GlobWorld create_world() {
|
|
|
|
|
return c; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* |
|
|
|
|
* Run once, intialises the game. |
|
|
|
|
* |
|
|
|
|
*/ |
|
|
|
|
void startgame(SDL_Renderer * ren) { |
|
|
|
|
load_fonts(); |
|
|
|
|
get_input_map(); |
|
|
|
@ -1663,8 +1733,6 @@ void startgame(SDL_Renderer * ren) {
@@ -1663,8 +1733,6 @@ void startgame(SDL_Renderer * ren) {
|
|
|
|
|
|
|
|
|
|
SDL_GetRendererOutputSize(ren, &width, &height); |
|
|
|
|
|
|
|
|
|
// player = get_player(200,1300);
|
|
|
|
|
|
|
|
|
|
get_floor_ceiling();
|
|
|
|
|
Vect stpos = *world.uniques_index[ROOM_W]->room->ceil.items[2]->collision_poly; |
|
|
|
|
player = get_player(stpos.x, stpos.y - 15); |
|
|
|
@ -1684,14 +1752,17 @@ void startgame(SDL_Renderer * ren) {
@@ -1684,14 +1752,17 @@ void startgame(SDL_Renderer * ren) {
|
|
|
|
|
game_paused = 0; |
|
|
|
|
viewport_pos.x = player.physics->position.x - width / 2; |
|
|
|
|
viewport_pos.y = player.physics->position.y - height / 2; |
|
|
|
|
|
|
|
|
|
//get_room();
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
double get_abs(double x,double y) { |
|
|
|
|
return (sqrt(x*x + y*y)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* |
|
|
|
|
* Make a player walk along the ground. Only enabled in debug mode. |
|
|
|
|
* |
|
|
|
|
*/ |
|
|
|
|
void walk_player(int x, int y) { |
|
|
|
|
|
|
|
|
|
set_motor_status(player.physics, M_PLAYER_WALK, true); |
|
|
|
@ -1704,6 +1775,12 @@ void walk_player(int x, int y) {
@@ -1704,6 +1775,12 @@ void walk_player(int x, int y) {
|
|
|
|
|
add_motor_newtons(glob_player->physics, M_PLAYER_WALK, 100 *5* x , 100 * 5 * y); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* |
|
|
|
|
* Handle non-window events pertaining to the game logic. Window events are |
|
|
|
|
* handled in main. Bindings are defined in controlscheme.c. |
|
|
|
|
* |
|
|
|
|
*/ |
|
|
|
|
void handle_input_event(SDL_Event event) { |
|
|
|
|
SDL_Scancode sc = event.key.keysym.scancode; |
|
|
|
|
static bool mouse_down = false; |
|
|
|
@ -1804,7 +1881,10 @@ void handle_input_event(SDL_Event event) {
@@ -1804,7 +1881,10 @@ void handle_input_event(SDL_Event event) {
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* temporary storage variable *n should be initialised to 1 */ |
|
|
|
|
/*
|
|
|
|
|
* Basic PRNG for cross-platform consistency. |
|
|
|
|
* |
|
|
|
|
* temporary storage variable *n should be initialised to 1 */ |
|
|
|
|
int get_rand(int *n) { |
|
|
|
|
const unsigned c = 11; |
|
|
|
|
const unsigned m = (1 << 31) - 1; |
|
|
|
@ -1816,11 +1896,15 @@ int get_rand(int *n) {
@@ -1816,11 +1896,15 @@ int get_rand(int *n) {
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* |
|
|
|
|
* Entry point for update step. |
|
|
|
|
* |
|
|
|
|
*/ |
|
|
|
|
int step(void) {
|
|
|
|
|
static int first_run = 0; |
|
|
|
|
if (!first_run) { |
|
|
|
|
start_audio(); |
|
|
|
|
// play_game_sound(game_sounds.background, -1, BC_MUSIC);
|
|
|
|
|
first_run = 1; |
|
|
|
|
game_paused = 1; |
|
|
|
|
} |
|
|
|
|