commit aca29690679b950892d98fa7b2c345acba386b21
parent 6efcb129b7d389c59b2e98485eecfbc4ac1a7523
Author: Matsuda Kenji <info@mtkn.jp>
Date: Tue, 20 Dec 2022 15:46:43 +0900
add mass
Diffstat:
M | main.c | | | 95 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------------ |
M | obj.h | | | 43 | ++++++++++++++++++++++++++++++++++++++++++- |
2 files changed, 108 insertions(+), 30 deletions(-)
diff --git a/main.c b/main.c
@@ -11,6 +11,7 @@
#define INIT_WIDTH 800
#define INIT_HEIGHT 600
#define FPS 60
+#define BLOCK_COUNT 100
/* variables */
@@ -20,7 +21,7 @@ unsigned int win_width = INIT_WIDTH, win_height = INIT_HEIGHT;
GC pgc, fgc, bgc;
Atom wm_delete_window;
Obj *square;
-Obj *block;
+Obj *blocks[BLOCK_COUNT];
int quit = 0;
enum Keys {
Key_D,
@@ -55,8 +56,7 @@ void handle_inputs(void);
void end_menu(void);
void next_tick(float);
void cleanup(void);
-//int check_collision(Obj *, Obj *);
-//int handle_collision(Obj *, Obj *);
+
void
setup(void)
@@ -145,15 +145,24 @@ void
game_init(void)
{
if(!square) // not allocated
- if(!(square = obj_create(100, 100, 0, 0, 0, 0, 20, 20))){
+ if(!(square = obj_create(100, 100, 0, 0, 0, 0, 400, 20, 20))){
fprintf(stderr, "couldn't create object: square");
exit(1);
}
- if(!block) // not allocated
- if(!(block = obj_create(200, 200, 0, 0, 0, 0, 20, 20))){
- fprintf(stderr, "couldn't create object: block");
- exit(1);
- }
+ for (int i = 0; i < BLOCK_COUNT; i++){
+ struct timespec t;
+ clock_gettime(CLOCK_REALTIME, &t);
+ srand(t.tv_nsec);
+ if(!blocks[i]) // not allocated
+ if(!(blocks[i] = obj_create((float)rand()*win_width/(float)RAND_MAX,
+ (float)rand()*win_height/(float)RAND_MAX,
+ rand()*300.0/RAND_MAX - 150,
+ rand()*300.0/RAND_MAX - 150,
+ 0, 0, 100, 10, 10))){
+ fprintf(stderr, "couldn't create object: block");
+ exit(1);
+ }
+ }
square->px = 100;
square->py = 100;
@@ -190,6 +199,8 @@ game_play(void)
//handle_interactions(); //handle interactions between objects
handle_inputs();
obj_next_tick(square, 1.0/FPS);
+ for (int i = 0; i < BLOCK_COUNT; i++)
+ obj_next_tick(blocks[i], 1.0/FPS);
handle_collision();
clock_gettime(CLOCK_MONOTONIC, &ts);
@@ -197,7 +208,9 @@ game_play(void)
XClearArea(display, window, 0, 0, win_width, win_height, False);
draw_object(square, pgc);
- draw_object(block, bgc);
+ for (int i = 0; i < BLOCK_COUNT; i++){
+ draw_object(blocks[i], bgc);
+ }
//XDrawString(display, window, fgc, square->px, square->py, "player", 6);
}
}
@@ -276,54 +289,78 @@ handle_inputs(void)
}
}
- square->vx = 0;
if (key_state[Key_D] == Key_Down)
square->vx += 300;
+ else
+ square->vx -= 300;
if (key_state[Key_A] == Key_Down)
square->vx += -300;
+ else
+ square->vx -= -300;
- square->vy = 0;
if (key_state[Key_S] == Key_Down)
square->vy += 300;
+ else
+ square->vy -= 300;
if (key_state[Key_W] == Key_Down)
square->vy += -300;
+ else
+ square->vy -= -300;
+
+ if (square->vx > 300) square->vx = 300;
+ if (square->vx < -300) square->vx = -300;
+ if (square->vy > 300) square->vy = 300;
+ if (square->vy < -300) square->vy = -300;
}
void
handle_collision(void)
{
+ for (int i = 0; i < BLOCK_COUNT; i++){
+ if (blocks[i]->px <= 0){
+ blocks[i]->px = 0;
+ blocks[i]->vx *= -1;
+ }
+ if (win_width <= blocks[i]->px + blocks[i]->width){
+ blocks[i]->px = win_width - blocks[i]->width;
+ blocks[i]->vx *= -1;
+ }
+
+ if (blocks[i]->py <= 0){
+ blocks[i]->py = 0;
+ blocks[i]->vy *= -1;
+ }
+ if (win_height <= blocks[i]->py + blocks[i]->height){
+ blocks[i]->py = win_height - blocks[i]->height;
+ blocks[i]->vy *= -1;
+ }
+ }
+
if (square->px <= 0){
square->px = 0;
- square->vx = 0;
+ square->vx *= -1;
}
if (win_width <= square->px + square->width){
square->px = win_width - square->width;
- square->vx = 0;
+ square->vx *= -1;
}
-
if (square->py <= 0){
square->py = 0;
- square->vy = 0;
+ square->vy *= -1;
}
if (win_height <= square->py + square->height){
square->py = win_height - square->height;
- square->vy = 0;
+ square->vy *= -1;
}
- if (block->py < square->py + square->height &&
- square->py < block->py + block->height &&
- block->px < square->px + square->width &&
- square->px < block->px + block->width){
- if (square->ppy + square->height <= block->ppy){
- obj_move(block, block->px, square->py + square->height);
- }else if (block->ppy + block->height <= square->ppy){
- obj_move(block, block->px, square->py - block->height);
- }else if (square->ppx + square->width <= block->ppx){
- obj_move(block, square->px + square->width, block->py);
- }else if (block->ppx + block->width <= square->ppx){
- obj_move(block, square->px - block->width, block->py);
+ for (int i = 0; i < BLOCK_COUNT; i++){
+ for (int j = i; j < BLOCK_COUNT; j++){
+ obj_handle_collision(blocks[i], blocks[j]);
}
}
+ for (int i = 0; i < BLOCK_COUNT; i++){
+ obj_handle_collision(blocks[i], square);
+ }
}
diff --git a/obj.h b/obj.h
@@ -3,22 +3,26 @@ typedef struct Obj{
float px, py; //current position
float vx, vy; //velocity
float ax, ay; //acceleration
+ float m; //mass
float width, height;
} Obj;
Obj *obj_create(float px, float py,
float vx, float vy,
float ax, float ay,
+ float m,
float width, float height);
void obj_move(Obj *obj, float px, float py); // move obj to the pos
void obj_next_tick(Obj *obj, float dt); // move obj by velocity * dt
void obj_accel(Obj *obj, float ax, float ay); // accelerate obj by accel
-
+int obj_test_collision(Obj *obj1, Obj *obj2);
+void obj_handle_collision(Obj *obj1, Obj *obj2);
Obj
*obj_create(float px, float py,
float vx, float vy,
float ax, float ay,
+ float m,
float width, float height)
{
Obj *obj;
@@ -29,6 +33,7 @@ Obj
obj->vy = vy;
obj->ax = ax;
obj->ay = ay;
+ obj->m = m;
obj->width = width;
obj->height = height;
return obj;
@@ -58,3 +63,39 @@ obj_accel(Obj *obj, float ax, float ay)
obj->vx += ax;
obj->vy += ay;
}
+
+
+int
+obj_test_collision(Obj *obj1, Obj *obj2)
+{
+ return obj1->py < obj2->py + obj2->height &&
+ obj2->py < obj1->py + obj1->height &&
+ obj1->px < obj2->px + obj2->width &&
+ obj2->px < obj1->px + obj1->width;
+}
+
+void
+obj_handle_collision(Obj *obj1, Obj *obj2)
+{
+ if(!obj_test_collision(obj1, obj2))
+ return;
+
+ float v1, v2;
+ float m1 = obj1->m;
+ float m2 = obj2->m;
+
+ if (obj2->ppy + obj2->height <= obj1->ppy ||
+ obj1->ppy + obj1->height <= obj2->ppy){
+ v1 = obj1->vy;
+ v2 = obj2->vy;
+ obj1->vy = 2*m2/(m1+m2)*v2 + (m1-m2)/(m1+m2)*v1;
+ obj2->vy = 2*m1/(m1+m2)*v1 + (m2-m1)/(m1+m2)*v2;
+ }else if (obj2->ppx + obj2->width <= obj1->ppx ||
+ obj1->ppx + obj1->width <= obj2->ppx){
+ v1 = obj1->vx;
+ v2 = obj2->vx;
+ obj1->vx = 2*m2/(m1+m2)*v2 + (m1-m2)/(m1+m2)*v1;
+ obj2->vx = 2*m1/(m1+m2)*v1 + (m2-m1)/(m1+m2)*v2;
+ }
+
+}