我一直在僵尸街机游戏中工作,我正在尝试一个奇怪的问题。我创建了一个名为GameObject的类和一个名为Human的类,它继承自GameOBject,然后我声明了另外两个调用;僵尸和玩家。问题是当我创建这四个类的两个或更多个字符(实例)时游戏停止工作,我发现在Zombie和Player类中,问题只发生在我调用方法更新时(只有这些类使用它)。该方法应该控制每个角色的活动。 图形和动画精灵与角色分开管理,它们(角色)只调用一些方法来控制精灵更新,这些命令在更新屏幕时被处理。
我只是想让你告诉我发生了什么,我认为问题出在Zombie和Player类的更新方法中。
项目分为不同的文件。
我认为这不重要,但我使用的是CodeBlocks和tdm-gcc。
main.cpp中:
#include "game_classes.h"
bool working = true, redraw = true;
int main(){
init_game_classes();
Player player(200, 200);
std::vector<Zombie *> zombie_list;
for(unsigned int i = 0; i < 2; i++){
Zombie *zombie = new Zombie(i * 100, 12, &player);
zombie_list.push_back(zombie);
}
while(working){
input();
if(event.type == ALLEGRO_EVENT_TIMER){//main loop
player.update();
for(unsigned int i = 0; i < zombie_list.size(); i++){
zombie_list[i]->update();
}
redraw = true;
}
else if(event.type == ALLEGRO_EVENT_DISPLAY_CLOSE){
working = false;
}
if(redraw and al_is_event_queue_empty(event_queue)){//updating display
update_animated_models();
blit_models();
update_display();
redraw = false;
}
}
for(unsigned int i = 0; i < zombie_list.size(); i++)
delete zombie_list[i];
quit();
return 0;
}
render.h:
#include <vector>
#include <stdio.h>
#include <allegro5/allegro.h>
#include <allegro5/allegro_image.h>
int global_ticks_per_frame = 0;
ALLEGRO_BITMAP *map_background = NULL;
class Model;
std::vector<Model *> model_list;
class Model{
protected:
int x = 0, y = 0, width, height;
int source_x = 0, source_y = 0, source_width, source_height;
public:
ALLEGRO_BITMAP *sheet = NULL;
bool hide = false;
int flags = 0;
Model(const char *path, int width, int height){
this->sheet = al_load_bitmap(path);
al_convert_mask_to_alpha(this->sheet, al_map_rgb(255, 0, 255));
this->source_width = al_get_bitmap_width(this->sheet);
this->source_height = al_get_bitmap_height(this->sheet);
this->width = width;
this->height = height;
model_list.insert(model_list.begin(), this);
}
Model(ALLEGRO_BITMAP *image, int width, int height){
this->sheet = image;
al_convert_mask_to_alpha(this->sheet, al_map_rgb(255, 0, 255));
this->source_width = al_get_bitmap_width(this->sheet);
this->source_height = al_get_bitmap_height(this->sheet);
this->width = width;
this->height = height;
model_list.insert(model_list.begin(), this);
}
~Model(){
al_destroy_bitmap(this->sheet);
model_list.erase(model_list.begin() + this->index());
}
void show(){
if(not this->hide){
al_draw_scaled_bitmap(this->sheet, this->source_x, this->source_y, this->source_width, this->source_height, x, y, width, height, this->flags);
}
}
void set_x(int x){
this->x = x;
}
unsigned int index(){
for(unsigned int i = 0; i < model_list.size(); i++){
if(model_list[i] == this)
return i;
}
}
bool set_y(int y){
this->y = y;
model_list.erase(model_list.begin() + this->index());
int this_relative_y = this->y + this->height;
unsigned int i = 0;
while(i < model_list.size()){
int from_list_relative_y = model_list[i]->y + model_list[i]->height;
if(this_relative_y < from_list_relative_y){
model_list.insert(model_list.begin() + i, this);
return false;
}
i += 1;
}
model_list.push_back(this);
return false;
}
int get_y(){
return this->y;
}
int get_x(){
return this->x;
}
unsigned int get_width(){
return this->width;
}
unsigned int get_height(){
return this->height;
}
};
void blit_models(){
for(unsigned int i = 0; i < model_list.size(); i++)
model_list[i]->show();
}
class AnimatedModel;
std::vector<AnimatedModel *> animated_model_list;
class AnimatedModel : public Model{
private:
unsigned int ticks_per_frame, ticks_counter = 0;
unsigned int current_frame = 0, frame_count;
public:
bool stop = false;
void set_speed(unsigned int new_speed){
this->ticks_per_frame = new_speed;
}
AnimatedModel(const char *path, unsigned int frames, unsigned int ticks_per_frame, int width, int height) : Model(path, width, height){
this->ticks_per_frame = ticks_per_frame;
this->frame_count = frames;
this->source_width /= frames;
animated_model_list.push_back(this);
}
AnimatedModel(ALLEGRO_BITMAP *image, unsigned int frames, unsigned int ticks_per_frame, int width, int height) : Model(image, width, height){
this->ticks_per_frame = ticks_per_frame;
this->frame_count = frames;
this->source_width /= frames;
animated_model_list.push_back(this);
}
~AnimatedModel(){
for(unsigned int i = 0; i < animated_model_list.size(); i++){
if(animated_model_list[i] == this){
animated_model_list.erase(animated_model_list.begin() + i);
}
}
}
void fix_sheet_looking(){
if(not this->stop)
this->source_x = this->current_frame*this->source_width;
}
void play(){
if(this->ticks_counter >= this->ticks_per_frame + global_ticks_per_frame){
this->current_frame += 1;
if(this->current_frame >= this->frame_count)
this->current_frame = 0;
this->ticks_counter = 0;
}
else{
this->ticks_counter += 1;
}
}
void update(){
if(not this->stop){
this->play();
this->fix_sheet_looking();
}
}
void set_frame(unsigned int i){
this->current_frame = i;
}
unsigned int get_frame(){
return this->current_frame;
}
};
void update_animated_models(){
for(unsigned int i = 0; i < animated_model_list.size(); i++)
animated_model_list[i]->update();
}
game_classes.h:
#include "render.h"
#include "touch.h"
#include "window_control.h"
#include <string>
#include <iostream>
ALLEGRO_BITMAP *zombie_sprite = NULL;
ALLEGRO_BITMAP *human_sprite = NULL;
void init_game_classes(){
init_window_control();
zombie_sprite = al_load_bitmap("textures/zombie/sprite.png");
human_sprite = al_load_bitmap("textures/human/sprite.png");
}
int control_key_up = ALLEGRO_KEY_UP, control_key_down = ALLEGRO_KEY_DOWN, control_key_right = ALLEGRO_KEY_RIGHT, control_key_left = ALLEGRO_KEY_LEFT;
int control_key_run = ALLEGRO_KEY_Z;
HitBoxList character_body_reg;
HitBoxList item_body_reg;
class GameObjec{
protected:
unsigned int walking_speed;
HitBoxList *last_coll_test = NULL;
int last_x, last_y;
int body_high;
int left_distance;
public:
HitBox *body = NULL;
AnimatedModel *sprite = NULL;
void set_x(int x){
this->sprite->set_x(x);
this->last_x = this->body->x;
this->body->x = x + this->left_distance;
}
void set_y(int y){
this->sprite->set_y(y);
this->last_y = this->body->y;
this->body->y = y + this->body_high;
}
int get_x(){
return this->sprite->get_x();
}
int get_y(){
return this->sprite->get_y();
}
void slide_x(short int direction){
character_body_reg.pop(this->body);
this->last_coll_test = this->body->slide_x(this->walking_speed*direction, &character_body_reg);
character_body_reg.push(this->body);
this->set_x(this->body->x - this->left_distance);
}
void slide_y(short int direction){
character_body_reg.pop(this->body);
this->last_coll_test = this->body->slide_y(this->walking_speed*direction, &character_body_reg);
character_body_reg.push(this->body);
this->set_y(this->body->y - this->body_high);
}
void show_hitbox(){
al_draw_rectangle(this->body->x, this->body->y, this->body->x + this->body->width, this->body->y + this->body->height, al_map_rgb(255, 0, 0), 1);
}
GameObjec(int x, int y, unsigned int walking_speed, const char *sprite_image_path, int frames, int ticks_per_frame, int sprite_width, int sprite_height, int body_high, int body_len){
this->walking_speed = walking_speed;
this->body_high = body_high;
this->sprite = new AnimatedModel(sprite_image_path, frames, ticks_per_frame, sprite_width, sprite_height);
this->left_distance = (this->sprite->get_width() - body_len)/2;
this->body = new HitBox;
this->sprite->set_x(x);
this->sprite->set_y(y);
this->body->width = body_len;
this->body->height = this->sprite->get_height() - this->body_high;
this->body->x = x + left_distance;
this->body->y = y + this->body_high;
this->last_x = this->body->x;
this->last_y = this->body->y;
character_body_reg.push(this->body);
}
~GameObjec(){
delete this->sprite;
character_body_reg.pop(this->body);
delete this->body;
}
void draw_hitbox(){
al_draw_rectangle(this->body->x, this->body->y, this->body->x + this->body->width, this->body->y + this->body->height, al_map_rgb(255, 0, 0), 0);
}
};
class Human : public GameObjec{
protected:
bool walking = false;
public:
Human(int x, int y, const char *sprite_image_path) : GameObjec(x, y, 2, sprite_image_path, 2, 7, 64, 80, 60, 32){}
~Human(){}
void walk_down(){
this->slide_y(1);
this->sprite->stop = false;
this->walking = true;
}
void walk_up(){
this->slide_y(-1);
this->sprite->stop = false;
this->walking = true;
}
void walk_right(){
this->slide_x(1);
this->sprite->stop = false;
this->sprite->flags = 0;
this->walking = true;
}
void walk_left(){
this->slide_x(-1);
this->sprite->stop = false;
this->sprite->flags = ALLEGRO_FLIP_HORIZONTAL;
this->walking = true;
}
};
class Player : public Human{
public:
Player(int x, int y) : Human(x, y, "textures/human/sprite.png"){
}
void control(){
if(get_key(control_key_down))
this->walk_down();
else if(get_key(control_key_up))
this->walk_up();
if(get_key(control_key_right))
this->walk_right();
else if(get_key(control_key_left))
this->walk_left();
if(not this->walking){
this->sprite->set_frame(0);
this->sprite->fix_sheet_looking();
this->sprite->stop = true;
}
if(this->last_x == this->body->x and this->last_y == this->body->y)
this->walking = false;
}
void update(){
this->control();
}
};
class Zombie : public Human{
private:
//Player *to_kill;
int to_kill_x, to_kill_y;
unsigned int walk_ticks_counter = 0, follow_ticks_counter = 0;
public:
Player *to_kill;
void fix_to_kill_position(){
if(this->to_kill){
this->to_kill_x = this->to_kill->body->x;
this->to_kill_y = this->to_kill->body->y;
}
else{
this->to_kill_x = this->body->x;
this->to_kill_y = this->body->y;
}
}
Zombie(int x, int y, Player *to_kill) : Human(x, y, "textures/zombie/sprite.png"){
this->sprite->set_speed(23);
this->walking_speed = 1;
this->to_kill = to_kill;
this->fix_to_kill_position();
}
void control(){
if(this->body->y < to_kill_y)
this->walk_down();
else if(this->body->y > to_kill_y)
this->walk_up();
if(this->body->x < to_kill_x)
this->walk_right();
else if(this->body->x > to_kill_x)
this->walk_left();
if(not this->walking){
this->sprite->set_frame(0);
this->sprite->fix_sheet_looking();
this->sprite->stop = true;
}
}
void update(){
if(this->follow_ticks_counter == 78){
this->fix_to_kill_position();
this->follow_ticks_counter = 0;
}
else{
this->follow_ticks_counter += 1;
}
if(this->walk_ticks_counter == 2){
this->control();
this->walk_ticks_counter = 0;
}
else{
this->walk_ticks_counter += 1;
}
if(this->last_x == this->body->x and this->last_y == this->body->y)
this->walking = false;
}
};