Skip to content
This repository has been archived by the owner on Aug 10, 2021. It is now read-only.

Commit

Permalink
优化性能,完善碰撞检测,完善游戏细节
Browse files Browse the repository at this point in the history
  • Loading branch information
Wider committed Apr 13, 2020
1 parent 39e92f3 commit 1e807a0
Show file tree
Hide file tree
Showing 8 changed files with 137 additions and 101 deletions.
64 changes: 4 additions & 60 deletions BaseObject.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,8 @@ bool Vector::operator != (const Vector& rhs) const {
if(*this == rhs) return false;
else return true;
}
double Vector::x() { return (_x); }
double Vector::y() { return (_y); }
double Vector::x() const { return (_x); }
double Vector::y() const { return (_y); }
void Vector::x(double x) { _x = x; }
void Vector::y(double y) { _y = y; }
void Vector::set(double x, double y) { _x = x, _y = y; }
Expand All @@ -62,6 +62,8 @@ void Figure::update(int x, int y) {
for(auto& i : figures)
{
if(i.tigger()) {
if(i.name!="rock0"&&i.name!="rock1")
//cout << i.name << endl;
if(_status != i.name) {
time_tick = steady_clock::now();
figure_cnt = 0;
Expand Down Expand Up @@ -121,63 +123,5 @@ void BaseObject::update(double time) {
void BaseObject::show(Vector& offset) {
figure.update(static_cast<int>(round(position.x()) + offset.x()), static_cast<int>(round(position.y()) + offset.y()));
}
bool BaseObject::block_crash(BaseObject& t,bool left_exist_object,bool right_exist_object) {
//if(
// position.x() > t.position.x() - figure.width() && position.x() < t.position.x() + t.figure.width()
// &&
// position.y() > t.position.y() - figure.height() && position.y() < t.position.y() + t.figure.height()
// )
// return true;
//cout << t.position.x() << " " << t.position.y() << endl;
int px = static_cast<int>(round(position.x())),
py = static_cast<int>(round(position.y())),
tpx = static_cast<int>(round(t.position.x())),
tpy = static_cast<int>(round(t.position.y()));

//上碰撞(相对被撞物体)
if(px + width() -1 >= tpx && px <= tpx + t.width() -1 &&
py + height() >= tpy && py < tpy) {
if(velocity.y() > 0) {
velocity.y(0);
position.y((double)tpy - height());
}
return true;
}
//下碰撞
if(px + width() -1 >= tpx && px <= tpx + t.width() -1 &&
py + height() -1 > tpy + height() -1 && py <= tpy + t.height()) {
if(velocity.y() < 0) {
velocity.y(0);
position.y((double)tpy + t.height());
}
return true;
}
//左碰撞
if(px + width() >= tpx && px < tpx &&
py + height() >= tpy && py <= tpy + t.height()) {
if(!left_exist_object) {
if(velocity.x() > 0) {
velocity.x(0);
position.x((double)tpx - width());
}
return true;
}
}
//右碰撞
if(px + width() > tpx + t.width()&& px <= tpx + t.width() &&
py + height() >= tpy && py <= tpy + t.height()) {
if(!right_exist_object) {
if(velocity.x() < 0) {
velocity.x(0);
position.x((double)tpx + t.width());
}
return true;
}
}
return false;
}
//bool BaseObject::pxiel_crash() {
//
//}


17 changes: 11 additions & 6 deletions BaseObject.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
#include <chrono>
#include "Global.h"


#define GRAVITY 0.0036

class Vector {
private:
Expand All @@ -31,25 +31,31 @@ class Vector {
bool operator == (const Vector& rhs) const;
bool operator == (const double rhs) const;
bool operator != (const Vector& rhs) const;
double x();
double y();
double x() const;
double y() const;
void x(double x);
void y(double y);
void set(double x, double y);
};
class Position: public Vector {
public:
using Vector::Vector;
Position():Vector(){}
Position(const Vector& t) { x(t.x()), y(t.y()); }
using Vector::operator=;
};
class Velocity: public Vector {
public:
using Vector::Vector;
Velocity():Vector() {}
Velocity(const Vector& t) { x(t.x()), y(t.y()); }
using Vector::operator=;
};
class Acceleration: public Vector {
public:
using Vector::Vector;
Acceleration():Vector() {}
Acceleration(const Vector& t) { x(t.x()), y(t.y()); }
using Vector::operator=;
};
struct FigureData {
Expand Down Expand Up @@ -89,15 +95,14 @@ class BaseObject
Velocity velocity;
Acceleration acceleration;
Figure figure;
BaseObject():_width(0),_height(0),position(), velocity(), acceleration(0, 0.004), figure(){}
BaseObject():_width(0),_height(0),position(), velocity(), acceleration(0, GRAVITY), figure(){}
int side_crash = 0;
int width();
int height();
void width(int w);
void height(int h);
void update(double time);
void show(Vector& offset);
bool block_crash(BaseObject& t, bool left_exist_object, bool right_exist_object);
bool pxiel_crash();
};


Expand Down
1 change: 0 additions & 1 deletion Global.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
#pragma once
#ifndef _GLOBAL_H_
#define _GLOBAL_H_

#define WINDOWS_WIDTH 700
#define WINDOWS_HEIGHT 504

Expand Down
85 changes: 81 additions & 4 deletions Map.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ void Map::init(BaseObject* h)
//单元格为35*35的方格,全地图横向228个单元,纵向14个单元
//注意坐标是从0开始的
//测试用
rocket.push_back(Rocket(0 * unit_length, 10 * unit_length, 1 * unit_length, 1 * unit_length, "rock1"));
rocket.push_back(Rocket(0 * unit_length, 10 * unit_length, 1 * unit_length , 1 * unit_length, "rock1"));
rocket.push_back(Rocket(0 * unit_length, 11 * unit_length, 1 * unit_length, 1 * unit_length, "rock1"));
rocket.push_back(Rocket(2 * unit_length, 10 * unit_length, 1 * unit_length, 1 * unit_length, "rock1"));
rocket.push_back(Rocket(2 * unit_length, 11 * unit_length, 1 * unit_length, 1 * unit_length, "rock1"));
Expand Down Expand Up @@ -118,11 +118,44 @@ bool Map::right_exist_object(BaseObject& t)

void Map::check_crash()
{
int flag = 0;
for(auto &i : rocket) {
if(i.position.x() > hero->position.x() + hero->width() || i.position.x() + i.width() < hero->position.x())
continue;
hero->block_crash(i, left_exist_object(i), right_exist_object(i));
//if(i.position.x() > hero->position.x() + hero->width() || i.position.x() + i.width() < hero->position.x())
// continue;
//hero->block_crash(i, left_exist_object(i), right_exist_object(i));
bool l = left_exist_object(i),
r = right_exist_object(i);
string str = collision(*hero, i,l,r);
if(str == "left")
flag = (1<<1)|flag;//0没有 1右 2左 3左右
if(str == "right")
flag = (1<<0)|flag;
if(str != "") {
//cout << str <<' '<<i.type()<<' '<<i.position.x()/36<<' '<<i.position.y()/36<< endl;
if(str == "top") {
if(hero->velocity.y() > 0)
hero->velocity.y(0);
hero->position.y(i.position.y() - hero->height());
}
else if(str == "bottom") {
if(hero->velocity.y()<0)
hero->velocity.y(0);
hero->position.y(i.position.y() + i.height());
}
else if(str == "left") {
if(hero->velocity.x() > 0)
hero->velocity.x(0);
hero->position.x(i.position.x() - hero->width());
}
else if(str == "right") {
if(hero->velocity.x() < 0)
hero->velocity.x(0);
hero->position.x(i.position.x() + i.width());
}
}
}
if(flag) hero->side_crash = flag;
else hero->side_crash = 0;

//vector<Rocket>:: reverse_iterator l;
//vector<Rocket>::iterator r;
Expand Down Expand Up @@ -150,3 +183,47 @@ void Map::check_crash()
//}

}


string Map::collision(BaseObject &a,BaseObject &b,bool left_exist_object,bool right_exist_object) {

int ax = static_cast<int>(round(a.position.x())),
ay = static_cast<int>(round(a.position.y())),
bx = static_cast<int>(round(b.position.x())),
by = static_cast<int>(round(b.position.y()));
//上碰撞(a相对被撞物体b)
if(ax + a.width() > bx && ax < bx + b.width() &&
ay + a.height() >= by && ay < by) {
if(a.position.x() < b.position.x() && a.position.x() + a.width() < b.position.x() + b.width() && a.position.x() + a.width() - b.position.x() < a.position.y() + a.height() - b.position.y())
return "left";
if(a.position.x() > b.position.x() && a.position.x() + a.width() > b.position.x() + b.width() && b.position.x() + b.width() - a.position.x() < a.position.y() + a.height() - b.position.y())
return "right";
return "top";
}
//下碰撞
else if(ax + a.width() > bx && ax < bx + b.width() &&
ay + a.height() > by + b.height() && ay < by + b.height()) {
if(a.position.x() < b.position.x() && a.position.x() + a.width() < b.position.x() + b.width() && a.position.x() + a.width() - b.position.x() < b.position.y() + b.height() - a.position.y())
return "left";
if(a.position.x() > b.position.x() && a.position.x() + a.width() > b.position.x() + b.width() && b.position.x() + b.width() - a.position.x() < b.position.y() + b.height() - a.position.y())
return "right";
return "bottom";
}
//左碰撞
else if(ax + a.width() >= bx && ax < bx &&
ay + a.height() >= by && ay < by + b.height()) {
if(!left_exist_object) {
return "left";
}
}
//右碰撞
else if(ax + a.width() > bx + b.width() && ax <= bx + b.width() &&
ay + a.height() >= by && ay < by + b.height()) {
if(!right_exist_object) {
//cout << "a.x:" << ax << "\t\ta.y:" << ay << "\t\ta.width:" << a.width() << "\ta.height:" << a.height() << endl;
//cout << "b.x:" << bx << "\t\tb.y:" << by << "\t\tb.width:" << b.width() << "\tb.height:" << b.height() << endl;
return "right";
}
}
return "";
}
1 change: 1 addition & 0 deletions Map.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ class Map
bool left_exist_object(BaseObject& t);
bool right_exist_object(BaseObject& t);
void check_crash();
string collision(BaseObject& a, BaseObject& b, bool left_exist_object, bool right_exist_object);
};


Expand Down
35 changes: 20 additions & 15 deletions Mario.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,14 @@ void Mario::run(double speed) {
velocity.x(speed);
else
velocity.x(-speed);
if(side_crash == 1 && velocity.x() < 0)velocity.x(0);
if(side_crash == 2 && velocity.x() > 0)velocity.x(0);
if(side_crash == 3)velocity.x(0);

}

void Mario::jump(double speed) {
if(figure.status() == "jumpping" || figure.status() == "falling") return;
position.y(position.y());
velocity.y(speed);
}

Expand Down Expand Up @@ -39,34 +42,36 @@ void Mario::init() {
vector<IMAGE> imgs, masks;
IMAGE temp;

for(int i = 0; i < 3; i++) {
SetWorkingImage(&origin);
getimage(&temp, width + width * i, 0, width, height);
imgs.push_back(temp);
SetWorkingImage(&organ_mask);
getimage(&temp, width + width * i, 0, width, height);
masks.push_back(temp);
}
figure.addFigure("running", imgs, masks, [this]()->bool {
if(velocity.x() != 0 && velocity.y() == 0) return true;
return false;
});

imgs.clear(); masks.clear();
SetWorkingImage(&origin);
getimage(&temp, 0, 0, width, height);
imgs.push_back(temp);
SetWorkingImage(&organ_mask);
getimage(&temp, 0, 0, width, height);
masks.push_back(temp);
figure.addFigure("still", imgs, masks, [this]()->bool {
if(figure.status() == "jumpping") return false;
if(velocity.x() == 0 && velocity.y() == 0) return true;
return false;
});
figure.addFigure("falling", imgs, masks, [this]()->bool {
if(velocity.y() > 0) return true;
return false;
});
imgs.clear(); masks.clear();
for(int i = 0; i < 3; i++) {
SetWorkingImage(&origin);
getimage(&temp, width + width * i, 0, width, height);
imgs.push_back(temp);
SetWorkingImage(&organ_mask);
getimage(&temp, width + width * i, 0, width, height);
masks.push_back(temp);
}
figure.addFigure("running", imgs, masks, [this]()->bool {
if(figure.status() == "jumpping") return false;
if(velocity.x() != 0 && velocity.y() == 0) return true;
return false;
});


imgs.clear(); masks.clear();
SetWorkingImage(&origin);
Expand Down
35 changes: 20 additions & 15 deletions 超级马里奥.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,28 +59,33 @@ int main()

BeginBatchDraw();

const int TICKS_PER_SECOND = 60;
const int SKIP_TICKS = 1000 / TICKS_PER_SECOND;
const int MAX_FRAMESKIP = 5;
const int max_ups = 120;
const int max_fps = 120;

const int update_skip_time = 1000 / max_ups;
const int frame_skip_time = 1000 / max_fps;

using namespace std::chrono;

auto next_game_tick = steady_clock::now();
int loops;
double interpolation;
auto update_time_tick = steady_clock::now();
auto frame_time_tick = steady_clock::now();

double update_time_interval;
double frame_time_interval;

bool game_is_running = true;
while(game_is_running) {

loops = 0;
while(steady_clock::now() > next_game_tick&& loops < MAX_FRAMESKIP) {
auto now = steady_clock::now();
update_time_interval = duration<double, std::milli>(now - update_time_tick).count();
if(update_time_interval >= update_skip_time) {
update();
next_game_tick += milliseconds(SKIP_TICKS);
loops++;
update_time_tick = now;
}
frame_time_interval = duration<double, std::milli>(now - frame_time_tick).count();
if(frame_time_interval >= frame_skip_time) {
reflush(frame_time_interval);
frame_time_tick = now;
}

interpolation = duration<double, std::milli>(steady_clock::now() + milliseconds(SKIP_TICKS) - next_game_tick).count()
/ double(SKIP_TICKS);
reflush(interpolation);
}

EndBatchDraw();
Expand Down
Binary file modified 超级马里奥.exe
Binary file not shown.

0 comments on commit 1e807a0

Please sign in to comment.