使用C ++ Win32实现重力翻转力学 [英] Implementing gravity flipping mechanics using C++ Win32

查看:143
本文介绍了使用C ++ Win32实现重力翻转力学的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图想一个有效的方式实现重力翻转机制到我的C ++ Win32游戏。虽然我不是很流利的语言,这就是为什么我在这里问。



我有:




  • 存储播放器属性的类(如位置和大小,以及一些函数)。

  • 消息路由器,接收用户(和其他来源)发送的消息。

  • 这些讯息包括播放器输入。我处理消息路由器中的输入,然后调用播放器类上的函数。



我坚持如何实现重力翻转机械。这是一个免费的转轮游戏。玩家朝向窗口的右侧运行,并且在轻击一个键之后,玩家角色将在正常(向下)重力或倒转(向上)重力之间交替。



我已经考虑的方法是使用do-while。这个问题是用户必须等待do-while完成。也就是说,如果玩家没有到达屏幕顶部,则继续向上移动(反向重力)。



我想到了其他方法,但我不认为他们值得尝试。



任何人都可以提出建议吗?



提前感谢:)



更新



这里是我一直在使用的代码和当前的问题一旦玩家已经到达屏幕的底部或顶部。我似乎不能改变重力。但是它允许我在玩家触摸顶部或底部窗口边缘之前这样做。
为什么是这样?



随意批评我的代码,告诉我如何改善我。



Main.cpp

  #includeBaseWindow.h
#包括GameWindow.h

int APIENTRY WinMain(HINSTANCE h_instance,HINSTANCE h_prev_instance,LPSTR lp_cmd_line,int n_cmd_show){
//创建游戏窗口
GameWindow game_window(h_instance, TEXT(GameWindow));
game_window.Register();

//创建基本窗口
BaseWindow base_window(TEXT(BaseWindow),game_window.ClassName());
bas_window.Create();
base_window.Show();

//泵消息
MSG消息;
int status;
while((status = GetMessage(& messages,0,0,0))!= 0){
if(status == -1){
// Break;
break;
}
TranslateMessage(& messages);
DispatchMessage(& messages);
}
return messages.wParam;

}

AbstractWindow.h p>

  #pragma once 
#ifndef __ABSTRACT_WINDOW_H__
#define __ABSTRACT_WINDOW_H__

#include< ; Windows.h>

类AbstractWindow {
public:
AbstractWindow();
〜AbstractWindow();

virtual bool Create();

static LRESULT CALLBACK MessageRouter(HWND,UINT,WPARAM,LPARAM);

protected:
HWND hwnd_;

DWORD style_ex_;
LPCTSTR class_name_;
LPCTSTR window_name_;
DWORD style_;
int x_;
int y_;
int width_;
int height_;
HWND parent_;
HMENU menu_;
HINSTANCE h_instance_;
LPVOID param_;

//位图变量 - 开始
// thw结构窗口宽度和高度
RECT rect_;
//处理设备上下文
HDC hdc_;
//处理设备上下文 - 后台缓冲区
HDC back_buffer_;
// Bitmap - Front
HBITMAP bitmap_; // Bitmap
//位图变量 - 结束


//默认处理程序
virtual bool OnCreate(HWND)= 0;
virtual bool OnCommand(int,int)= 0;
virtual bool OnDestroy()= 0;

virtual bool OnPaint(HWND,WPARAM)= 0;

//播放器处理程序
virtual bool UpdatePlayerPosition(HWND,WPARAM)= 0;

};
#endif //!__ ABSTRACT_WINDOW_H__

AbstractWindow.cpp / p>

  #includeAbstractWindow.h

AbstractWindow :: AbstractWindow(){}

AbstractWindow ::〜AbstractWindow(){}

bool AbstractWindow :: Create(){
hwnd_ = CreateWindowEx(
style_ex_,
class_name_,
window_name_,
style_,
x_,
y_,
width_,
height_,
parent_,
menu_,
h_instance_,
this //指向这个类实例的指针
);

if(hwnd_){
OnCreate(hwnd_);
return true;
}
return false;
}

LRESULT CALLBACK AbstractWindow :: MessageRouter(HWND hwnd,UINT message,WPARAM w_param,LPARAM l_param){
AbstractWindow * abstract_window = 0;

static bool move = false;

if(message == WM_NCCREATE){
abstract_window =(AbstractWindow *)((LPCREATESTRUCT(l_param)) - > lpCreateParams);
SetWindowLong(hwnd,GWL_USERDATA,long(abstract_window));
return DefWindowProc(hwnd,message,w_param,l_param);
}
else {
abstract_window =(AbstractWindow *)(GetWindowLong(hwnd,GWL_USERDATA));
if(abstract_window){
switch(message){
case WM_COMMAND:
return abstract_window-> OnCommand(LOWORD(w_param),HIWORD(w_param));
case WM_DESTROY:
return abstract_window-> OnDestroy();
case WM_PAINT:
return abstract_window-> OnPaint(hwnd,w_param);
case WM_KEYDOWN:
return abstract_window-> UpdatePlayerPosition(hwnd,w_param);
默认值:
return DefWindowProc(hwnd,message,w_param,l_param);
}
}
else {
return DefWindowProc(hwnd,message,w_param,l_param);
}
}
}

** BaseWindow.h **
#pragma once
#ifndef __BASE_WINDOW_H__
#define __BASE_WINDOW_H__

#include< Windows.h>
#includeAbstractWindow.h
#includePlayer.h

class BaseWindow:public AbstractWindow {
public:
BaseWindow
〜BaseWindow();

BaseWindow(const TCHAR *,const TCHAR *);

//更新客户区时在屏幕上显示窗口
void Show();


private:

//玩家对象
玩家;

//处理程序
virtual bool OnCreate(HWND);
virtual bool OnCommand(int,int);
virtual bool OnDestroy();

virtual bool OnPaint(HWND,WPARAM);

//播放器处理程序
virtual bool UpdatePlayerPosition(HWND,WPARAM);


};
#endif //!__ BASE_WINDOW_H__

BaseWindow.cpp / p>

  #includeBaseWindow.h

#pragma region构造函数和析构函数

BaseWindow :: BaseWindow(){}

BaseWindow ::〜BaseWindow(){}

BaseWindow :: BaseWindow(const TCHAR * window_name,const TCHAR * class_name) :AbstractWindow(){
//成员变量在AbstractWindow中声明为受保护
window_name_ = window_name;
class_name_ = class_name;

//获取当前运行窗口的模块句柄
h_instance_ = GetModuleHandle(NULL);
style_ =(WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX);
x_ = CW_USEDEFAULT;
y_ = CW_USEDEFAULT
width_ = CW_USEDEFAULT;
height_ = CW_USEDEFAULT;
parent_ = NULL;
menu_ = NULL;

}

#pragma endregion

#pragma region函数

void BaseWindow :: Show(){
// hwnd_来自AbstractWindow类
ShowWindow(hwnd_,SW_SHOW);
UpdateWindow(hwnd_);
}

#pragma endregion

#pragma region基本处理程序

bool BaseWindow :: OnCreate(HWND hwnd){
MessageBox(hwnd,TEXT([BaseWindow] Window has been successfully created!),TEXT(SUCCESS),MB_OK);

GetClientRect(hwnd,& rect_);
width_ = rect_.right;
height_ = rect_.bottom;

//创建后台缓冲区
back_buffer_ = CreateCompatibleDC(NULL);
//获取设备上下文
hdc_ = GetDC(hwnd);
//创建位图
bitmap_ = CreateCompatibleBitmap(hdc_,width_,height_);
//选择位图
SelectObject(back_buffer_,bitmap_);
//发布
ReleaseDC(hwnd,hdc_);

return true;
}

bool BaseWindow :: OnCommand(int ctrl_id,int notify_code){

//低16位指定鼠标在$ b $上使用的元素b //高16位指定鼠标属性
// ctrl_id =低
// notify_code =高
return true;
}

bool BaseWindow :: OnDestroy(){
PostQuitMessage(0);
return true;
}

#pragma endregion

#pragma region其他处理程序

bool BaseWindow :: OnPaint(HWND hwnd,WPARAM w_param){

PAINTSTRUCT paint_struct;

//获取设备上下文
hdc_ = BeginPaint(hwnd,& paint_struct);

BitBlt(back_buffer_,0,0,width_,height_,NULL,NULL,NULL,WHITENESS);

if(player.WithinTopBounds()&&& amp; amp; amp; amp; player.WithinBottomBounds(height_)){
player.GravityMovement();
}


//选择Rectangle Brush
SelectObject(back_buffer_,CreateSolidBrush(RGB(player.SpecializerRed(),player.SpecializerGreen(),player.SpecializerBlue ())));
//在后台缓冲区中绘制矩形
Rectangle(back_buffer_,
player.X() - player.Width()/ 2,
player.Y .Height()/ 2,
player.X()+ player.Width()/ 2,
player.Y()+ player.Height()/ 2);

//显示后台缓冲区
BitBlt(hdc_,0,0,width_,height_,back_buffer_,0,0,SRCCOPY);
//重画屏幕
InvalidateRect(hwnd,NULL,false);

EndPaint(hwnd,& paint_struct);

return true;
}

#pragma region Player

bool BaseWindow :: UpdatePlayerPosition(HWND hwnd,WPARAM w_param){
if(w_param == VK_RIGHT){
if(player.withinRightBounds(width_)){
//向右移动
player.RightMovement();
}
}
if(w_param == VK_LEFT){
if(player.WithinLeftBounds()){
//向右移动
.LeftMovement();
}
}

if(w_param == VK_UP){
//向上移动
if(!player.WithinTopBounds()){
player.SetInverted(false);
}
player.SetInverted(true);

}
if(w_param == VK_DOWN){
if(!player.WithinBottomBounds(height_)){
player.SetInverted(true);
}
//向下移动
player.SetInverted(false);

}

返回true;
}

#pragma endregion



#pragma endregions

GameWindow.h

  #pragma once 
#ifndef __GAME_WINDOW_H__
#define __GAME_WINDOW_H__

#include< Windows.h>
#includeAbstractWindow.h

class GameWindow:protected WNDCLASSEX {
public:
GameWindow();
〜GameWindow();

GameWindow(HINSTANCE,const TCHAR *);

virtual bool Register();

virtual const TCHAR * ClassName()const;

protected:
UINT cb_size_;
UINT style_;
WNDPROC lpfn_wnd_proc_;
int cb_cls_extra_;
int cb_wnd_extra _;
HINSTANCE h_instance_;
HICON h_icon_;
HCURSOR h_cursor_;
HBRUSH hbr_background_;
LPCTSTR lpsz_menu_name_;
LPCTSTR lpsz_class_name_;
HICON h_icon_sm_;


};
#endif //!__ GAME_WINDOW_H__


** GameWindow.cpp **

#includeGameWindow.h

GameWindow :: GameWindow(){}

GameWindow ::〜GameWindow(){}

GameWindow :: GameWindow(HINSTANCE h_instance,const TCHAR * class_name){

//属于此窗口类的所有消息将发送到MsgRouter

hInstance = h_instance;
lpszClassName = class_name;

lpfnWndProc = AbstractWindow :: MessageRouter;
lpszMenuName = NULL;
cbSize = sizeof(WNDCLASSEX);
cbClsExtra = NULL;
cbWndExtra = NULL;
//防止窗口重绘
style = 0;
hIcon = LoadIcon(NULL,IDI_APPLICATION);
hIconSm = LoadIcon(NULL,IDI_APPLICATION);
hCursor = LoadCursor(NULL,IDC_HAND);
hbrBackground = CreateSolidBrush(RGB(125,255,255));

}

const TCHAR * GameWindow :: ClassName()const {
return lpszClassName;
}

bool GameWindow :: Register(){
return((RegisterClassEx(this))?true:false)
}

Player.h
$ b

  #pragma once 
#ifndef __PLAYER_H__
#define __PLAYER_H__

#include< Windows.h> ;
#include< algorithm>
#include< string>
using namespace std;

class Player {
public:
Player();
〜Player();

// Mutator
void SetX(float);
void SetY(float);
void SetPlayerSpeed(float);

void SetSpecializerState(string);
void SetInverted(bool);

//访问者
float X()const;
float Y()const;
int Width()const;
int Height()const;

int SpecializerRed()const;
int SpecializerGreen()const;
int SpecializerBlue()const;
string SpecializerState()const;

bool Inverted()const;


//播放器功能
void RightMovement();
void LeftMovement();
void GravityMovement();
//在边界检测内
bool WithinLeftBounds();
bool withinRightBounds(int);
bool WithinTopBounds();
bool WithinBottomBounds(int);


private:
//一般信息
float x_;
float y_;
int width_;
int height_;
float speed_;
float gravity_;
bool inverted_;

//玩家国家
int specializer_state_;
// RGB
int specializer_red_;
int specializer_green_;
int specializer_blue_;

void SetSpecializerColor(int);


};

#endif //!__ PLAYER_H__

Player.cpp

  #includePlayer.h


#pragma region构造函数和析构函数

Player :: Player(){

x_ = 200;
y_ = 200;
width_ = 50;
height_ = 50;
speed_ = 5.0f;
gravity_ = 0.2f;
inverted_ = false;

//专用器
//设置为默认专用器状态
specializer_state_ = 0;
specializer_red_ = 0;
specializer_green_ = 0;
specializer_blue_ = 0;
SetSpecializerColor(specializer_state_);

}

Player ::〜Player(){}

#pragma endregion

#pragma region Mutator

#pragma region位置属性

void Player :: SetX(float x){
x_ = x;
}
void Player :: SetY(float y){
y_ = y;
}

#pragma endregion

void Player :: SetInverted(bool inverted){
inverted_ = inverted;
}

#pragma region Specializer属性

void Player :: SetSpecializerState(string input_state){

if(input_state == NORMAL){
specializer_state_ = 0;
}
else if(input_state ==SHIELD){
specializer_state_ = 1;
}
else if(input_state ==SPEED){
specializer_state_ = 2;
}
else if(input_state ==PROJECTILE){
specializer_state_ = 3;
}
else if(input_state ==MULTIPLIER){
specializer_state_ = 4;
}

SetSpecializerColor(specializer_state_);

}

void Player :: SetSpecializerColor(int state){
if(specializer_state_ == 0){
// NORMAL - White
specializer_red_ = 255;
specializer_green_ = 255;
specializer_blue_ = 255;
}
else if(specializer_state_ == 1){
// SHIELD - Green
specializer_red_ = 255;
specializer_green_ = 153;
specializer_blue_ = 76;
}
else if(specializer_state_ == 2){
// SPEED - Blue
specializer_red_ = 0;
specializer_green_ = 0;
specializer_blue_ = 102;
}
else if(specializer_state_ == 3){
// PROJECTILE - 黄
specializer_red_ = 255;
specializer_green_ = 255;
specializer_blue_ = 0;
}
else if(specializer_state_ == 4){
// MULTIPLIER - Red
specializer_red_ = 204;
specializer_green_ = 0;
specializer_blue_ = 0;
}
}

#pragma endregion



#pragma endregion

#pragma区域访问器

#pragma region位置属性

float Player :: X()const {
return x_;
}

float Player :: Y()const {
return y_;
}

int Player :: Width()const {
return width_;
}

int Player :: Height()const {
return height_;
}

bool Player :: Inverted()const {
return inverted_;
}

#pragma endregion

#pragma region Specializer属性

int Player :: SpecializerRed()const {
return specializer_red_;
}

int Player :: SpecializerGreen()const {
return specializer_green_;
}

int Player :: SpecializerBlue()const {
return specializer_blue_;
}

string Player :: SpecializerState()const {

string specializer_state =;

if(specializer_state_ == 0){
specializer_state =NORMAL;
}
else if(specializer_state_ == 1){
specializer_state =SHIELD;
}
else if(specializer_state_ == 2){
specializer_state =SPEED;
}
else if(specializer_state_ == 3){
specializer_state =PROJECTILE;
}
else if(specializer_state_ == 4){
specializer_state =MULTIPLIER;
}

return specializer_state;
}

#pragma endregion

#pragma endregion

#pragma region功能

#pragma region运动

void Player :: RightMovement(){
x_ + = speed_;
}

void Player :: LeftMovement(){
x_ - = speed_;
}

void Player :: GravityMovement(){
if(inverted_){
// Upwards
if(min(0.0f,gravity_) == 0.0f){
gravity_ = -gravity_;
}
y_ + = gravity_;
}
else {
//向下
if(max(0.0f,gravity_)== 0.0f){
gravity_ = -gravity_;
}
y_ + = gravity_;
}
}

#pragma endregion

#pragma region在窗口边界内


bool播放器: :WithinLeftBounds(){
if(x_ - (width_ / 2)> 0){
return true;
}
return false;
}

bool Player :: withinRightBounds(int width){
if(x_ +(width_ / 2)< width){
return true;
}
return false;
}

bool Player :: WithinTopBounds(){
if(y_ - (height_ / 2)> 0){
return true;
}
return false;
}

bool Player :: WithinBottomBounds(int height){
if(y_ +(height_ / 2)< height){
return true;
}
return false;
}

#pragma endregion


#pragma endregion


解决方案

您的游戏应该有游戏循环



通常,一个非常基本的游戏循环如下:

  while(playing){
accept_input()
update_game_logic()
render()
}

update_game_logic()函数中,您将有一个更新播放器位置的部分。玩家的位置更新步骤通常看起来像一些混合:

  // 1.总结玩家的力量
// 2.添加current_gravity(正常或反转)
// 3.检查是否有碰撞并添加一个反力
//(如果接触地面添加力直接在地面对面,等于对象正在向下推的力)
// 4.使用某种形式的集成来解决位置
//例如添加力(* deltatime)到加速度,添加加速度(* deltatime)到速度,添加速度(* deltatime)到位置。

因为你是根据力量调整玩家的位置,所以你可以继续接受输入和渲染屏幕同时更新游戏逻辑。


I'm trying to think of an efficient way implementing gravity flipping mechanics into my C++ Win32 game. Although I'm not very fluent with the language, thats why I'm here to ask.

I have:

  • A class which stores the properties of the player (such as position and size, as well as some functions).
  • A Message Router which takes in messages sent from the user (and other sources).
  • These messages include the player inputs. I handle the inputs in the Message Router and then call the functions on the player class.

I'm stuck on how to implement the gravity flipping mechanic. This is a free runner game. The player runs towards the right side of the window, and after a tap of a key the player character will alternate between normal (downwards) gravity or inverted (upwards) gravity.

The approach which I have taken into account is using a do-while. The problem with this is that the user must wait until the do-while is complete. That is, if the player hasn't reach to the top of the screen keep moving up (inverted gravity).

I have thought of other approaches but I don't think they're worth trying. It just leads to some other trouble.

Any suggestions anyone ?

Thanks in advance :)

Update

Here is the code ive been working on and the current problem that i have to is that once the player has reached to the bottom or top of the screen. I can't seem to change the gravity. But it allows me to do that before the player touches the top or bottom window edge. Why is this ?

Feel free to criticize on my code and tell me how i can improve me.

Main.cpp

#include "BaseWindow.h"
#include "GameWindow.h"

int APIENTRY WinMain ( HINSTANCE h_instance, HINSTANCE h_prev_instance, LPSTR lp_cmd_line, int n_cmd_show ) {
    // Create the Game Window
    GameWindow game_window ( h_instance, TEXT ( "GameWindow" ) );
    game_window.Register ();

    // Create the Base Window
    BaseWindow base_window ( TEXT ( "BaseWindow" ), game_window.ClassName () );
    base_window.Create ();
    base_window.Show ();

    // Pump Messages
    MSG messages;
    int status;
    while ( ( status = GetMessage ( &messages, 0, 0, 0 ) ) != 0 ) {
        if ( status == -1 ) {
            // Break;
            break;
        }
        TranslateMessage ( &messages );
        DispatchMessage ( &messages );
    }
    return messages.wParam;

}

AbstractWindow.h

#pragma once
#ifndef __ABSTRACT_WINDOW_H__
#define __ABSTRACT_WINDOW_H__

#include <Windows.h>

class AbstractWindow {
    public:
        AbstractWindow ();
        ~AbstractWindow ();

        virtual bool Create ();

        static LRESULT CALLBACK MessageRouter ( HWND, UINT, WPARAM, LPARAM );

    protected:
        HWND hwnd_;

        DWORD style_ex_;
        LPCTSTR class_name_;
        LPCTSTR window_name_;
        DWORD style_;
        int x_;
        int y_;
        int width_;
        int height_;
        HWND parent_;
        HMENU menu_;
        HINSTANCE h_instance_;
        LPVOID param_;

        // Bitmap Variables - Start
        // Stucture for thw Window width and height
        RECT rect_;
        // Handle to Device Context
        HDC hdc_;
        // Handle to Device Context - Back Buffer
        HDC back_buffer_;
        // Bitmap - Front
        HBITMAP bitmap_; // Bitmap
        // Bitmap Variables - End


        // Default Handlers
        virtual bool OnCreate ( HWND ) = 0;
        virtual bool OnCommand ( int, int ) = 0;
        virtual bool OnDestroy () = 0;

        virtual bool OnPaint ( HWND, WPARAM ) = 0;

        // Player Handlers
        virtual bool UpdatePlayerPosition( HWND, WPARAM ) = 0;

};
#endif // !__ABSTRACT_WINDOW_H__

AbstractWindow.cpp

#include "AbstractWindow.h"

AbstractWindow::AbstractWindow () {}

AbstractWindow::~AbstractWindow () {}

bool AbstractWindow::Create () {
    hwnd_ = CreateWindowEx (
        style_ex_,
        class_name_,
        window_name_,
        style_,
        x_,
        y_,
        width_,
        height_,
        parent_,
        menu_,
        h_instance_,
        this                    // Pointer to this class instance
        );

    if ( hwnd_ ) {
        OnCreate(hwnd_);
        return true;
    }
    return false;
}

LRESULT CALLBACK AbstractWindow::MessageRouter ( HWND hwnd, UINT message, WPARAM w_param, LPARAM l_param ) {
    AbstractWindow* abstract_window = 0;

    static bool move = false;

    if ( message == WM_NCCREATE ) {
        abstract_window = ( AbstractWindow* ) ( ( LPCREATESTRUCT ( l_param ) )->lpCreateParams );
        SetWindowLong ( hwnd, GWL_USERDATA, long ( abstract_window ) );
        return DefWindowProc ( hwnd, message, w_param, l_param );
    }
    else {
        abstract_window = ( AbstractWindow* ) ( GetWindowLong ( hwnd, GWL_USERDATA ) );
        if ( abstract_window ) {
            switch ( message ) {
                case WM_COMMAND:
                    return abstract_window->OnCommand ( LOWORD ( w_param ), HIWORD ( w_param ) );
                case WM_DESTROY:
                    return abstract_window->OnDestroy ();
                case WM_PAINT:
                    return abstract_window->OnPaint ( hwnd, w_param);
                case WM_KEYDOWN:
                    return abstract_window->UpdatePlayerPosition( hwnd, w_param );
                default:
                    return DefWindowProc ( hwnd, message, w_param, l_param );
            }
        }
        else {
            return DefWindowProc ( hwnd, message, w_param, l_param );
        }
    }
}

**BaseWindow.h**
#pragma once
#ifndef __BASE_WINDOW_H__
#define __BASE_WINDOW_H__

#include <Windows.h>
#include "AbstractWindow.h"
#include "Player.h"

class BaseWindow : public AbstractWindow {
    public:
        BaseWindow ();
        ~BaseWindow ();

        BaseWindow ( const TCHAR*, const TCHAR* );

        // Display the window onto the screen while updating the client area
        void Show ();


    private:

        // Player Object
        Player player;  

        // Handlers
        virtual bool OnCreate ( HWND );
        virtual bool OnCommand ( int, int );
        virtual bool OnDestroy ();

        virtual bool OnPaint( HWND, WPARAM );

        // Player Handlers
        virtual bool UpdatePlayerPosition( HWND, WPARAM );


};
#endif // !__BASE_WINDOW_H__

BaseWindow.cpp

#include "BaseWindow.h"

#pragma region Constructor and Destructor

    BaseWindow::BaseWindow() {}

    BaseWindow::~BaseWindow() {}

    BaseWindow::BaseWindow( const TCHAR* window_name, const TCHAR* class_name ) : AbstractWindow() {
        // Member variables are declaried in AbstractWindow as Protected
        window_name_ = window_name;
        class_name_ = class_name;

        // Get the module handle for the window currently running
        h_instance_ = GetModuleHandle( NULL );
        style_ = ( WS_OVERLAPPED| WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX );
        x_ = CW_USEDEFAULT;
        y_ = CW_USEDEFAULT;
        width_ = CW_USEDEFAULT;
        height_ = CW_USEDEFAULT;
        parent_ = NULL;
        menu_ = NULL;

    }

#pragma endregion

#pragma region Functions

    void BaseWindow::Show() {
        // hwnd_ is from AbstractWindow Class
        ShowWindow( hwnd_, SW_SHOW );
        UpdateWindow( hwnd_ );
    }

#pragma endregion

#pragma region Basic Handlers

    bool BaseWindow::OnCreate( HWND hwnd ) {
        MessageBox( hwnd, TEXT( "[BaseWindow] Window has been successfully created!" ), TEXT( "SUCCESS" ), MB_OK );

        GetClientRect( hwnd, &rect_ );
        width_ = rect_.right;
        height_ = rect_.bottom;

        // Create the back buffer
        back_buffer_ = CreateCompatibleDC( NULL );
        // Get the Device Context
        hdc_ = GetDC( hwnd );
        // Create the Bitmap
        bitmap_ = CreateCompatibleBitmap( hdc_, width_, height_ );
        // Select the Bitmap
        SelectObject( back_buffer_, bitmap_ );
        // Release
        ReleaseDC( hwnd, hdc_ );

        return true;
    }

    bool BaseWindow::OnCommand( int ctrl_id, int notify_code ) {

        // Lower 16 bits specifies the element the mouse was used on
        // Upper 16 bits specifies the mouse properties
        // ctrl_id = Lower
        // notify_code = Upper
        return true;
    }

    bool BaseWindow::OnDestroy() {
        PostQuitMessage( 0 );
        return true;
    }

#pragma endregion

#pragma region Other Handlers

    bool BaseWindow::OnPaint( HWND hwnd, WPARAM w_param ) {

        PAINTSTRUCT paint_struct;

        // Get the Device Context
        hdc_ = BeginPaint( hwnd, &paint_struct );

        BitBlt( back_buffer_, 0, 0, width_, height_, NULL, NULL, NULL, WHITENESS );

        if ( player.WithinTopBounds() && player.WithinBottomBounds(height_) ) {
            player.GravityMovement();
        }


        // Select the Rectangle Brush
        SelectObject( back_buffer_, CreateSolidBrush( RGB( player.SpecializerRed(), player.SpecializerGreen(), player.SpecializerBlue() ) ) );
        // Draw the Rectangle on the back buffer
        Rectangle( back_buffer_,
                   player.X() - player.Width() / 2,
                   player.Y() - player.Height() / 2,
                   player.X() + player.Width() / 2,
                   player.Y() + player.Height() / 2);

        // Display the back buffer
        BitBlt( hdc_, 0, 0, width_, height_, back_buffer_, 0, 0, SRCCOPY );
        // Repaint the screen
        InvalidateRect( hwnd, NULL, false );

        EndPaint( hwnd, &paint_struct );

        return true;
    }

    #pragma region Player

        bool BaseWindow::UpdatePlayerPosition(HWND hwnd, WPARAM w_param ) {
            if ( w_param == VK_RIGHT ) {
                if ( player.withinRightBounds( width_ ) ) {
                    // Movement to the right
                    player.RightMovement();
                }
            }
            if ( w_param == VK_LEFT ) {
                if ( player.WithinLeftBounds() ) {
                    // Movement to right left
                    player.LeftMovement();
                }           
            }

            if ( w_param == VK_UP ) {               
                // Movement upwards
                if ( !player.WithinTopBounds() ) {
                    player.SetInverted( false );
                }
                player.SetInverted( true );

            }
            if ( w_param == VK_DOWN ) {
                if ( !player.WithinBottomBounds( height_ ) ) {
                    player.SetInverted( true );
                }
                // Movement downwards
                player.SetInverted( false );

            }

            return true;
        }

    #pragma endregion



#pragma endregions

GameWindow.h

#pragma once
#ifndef __GAME_WINDOW_H__
#define __GAME_WINDOW_H__

#include <Windows.h>
#include "AbstractWindow.h"

class GameWindow : protected WNDCLASSEX {
    public:
        GameWindow ();
        ~GameWindow ();

        GameWindow ( HINSTANCE, const TCHAR* );

        virtual bool Register ();

        virtual const TCHAR* ClassName () const;

    protected:
        UINT cb_size_;
        UINT style_;
        WNDPROC lpfn_wnd_proc_;
        int cb_cls_extra_;
        int cb_wnd_extra_;
        HINSTANCE h_instance_;
        HICON h_icon_;
        HCURSOR h_cursor_;
        HBRUSH hbr_background_;
        LPCTSTR lpsz_menu_name_;
        LPCTSTR lpsz_class_name_;
        HICON h_icon_sm_;


};
#endif // !__GAME_WINDOW_H__


**GameWindow.cpp**

#include "GameWindow.h"

GameWindow::GameWindow () {}

GameWindow::~GameWindow () {}

GameWindow::GameWindow ( HINSTANCE h_instance, const TCHAR* class_name ) {

    // All messages belonging to this Window Class will get sent to MsgRouter

    hInstance = h_instance;
    lpszClassName = class_name;

    lpfnWndProc = AbstractWindow::MessageRouter;
    lpszMenuName = NULL;
    cbSize = sizeof ( WNDCLASSEX );
    cbClsExtra = NULL;
    cbWndExtra = NULL;
    // Prevent Window from Redrawing
    style = 0;
    hIcon = LoadIcon ( NULL, IDI_APPLICATION );
    hIconSm = LoadIcon ( NULL, IDI_APPLICATION );
    hCursor = LoadCursor ( NULL, IDC_HAND );
    hbrBackground = CreateSolidBrush ( RGB ( 125, 255, 255 ) );

}

const TCHAR* GameWindow::ClassName () const {
    return lpszClassName;
}

bool GameWindow::Register () {
    return ( ( RegisterClassEx ( this ) ) ? true : false );
}

Player.h

#pragma once
#ifndef __PLAYER_H__
#define __PLAYER_H__

#include <Windows.h>
#include <algorithm>
#include <string>
using namespace std;

class Player {
    public:
        Player ();
        ~Player ();

        // Mutator
        void SetX ( float );
        void SetY ( float );
        void SetPlayerSpeed ( float );

        void SetSpecializerState ( string );
        void SetInverted( bool );

        // Accessor
        float X () const;
        float Y () const;
        int Width () const;
        int Height () const;

        int SpecializerRed () const;
        int SpecializerGreen () const;
        int SpecializerBlue () const;
        string SpecializerState () const;

        bool Inverted() const;


        // Player Functionality
        void RightMovement ();
        void LeftMovement ();
        void GravityMovement();
        // Within Bounds Detection
        bool WithinLeftBounds();
        bool withinRightBounds(int);
        bool WithinTopBounds();
        bool WithinBottomBounds(int);


    private:
        // General Information
        float x_;
        float y_;
        int width_;
        int height_;
        float speed_;
        float gravity_;
        bool inverted_;

        // Player States
        int specializer_state_;
        // RGB
        int specializer_red_;
        int specializer_green_;
        int specializer_blue_;

        void SetSpecializerColor (int);


};

#endif // !__PLAYER_H__

Player.cpp

#include "Player.h"


#pragma region Constructor and Destructor

Player::Player () {

    x_ = 200;
    y_ = 200;
    width_ = 50;
    height_ = 50;
    speed_ = 5.0f;
    gravity_ = 0.2f;
    inverted_ = false;

    // Specializer
    // Set to Default Specializer State
    specializer_state_ = 0;
    specializer_red_ = 0;
    specializer_green_ = 0;
    specializer_blue_ = 0;
    SetSpecializerColor ( specializer_state_ );

}

Player::~Player () {}

#pragma endregion

#pragma region Mutator

    #pragma region Position Properties

    void Player::SetX ( float x ) {
        x_ = x;
    }
    void Player::SetY ( float y ) {
        y_ = y;
    }

    #pragma endregion

    void Player::SetInverted( bool inverted ) {
        inverted_ = inverted;
    }

    #pragma region Specializer Properties

    void Player::SetSpecializerState ( string input_state ) {

        if ( input_state == "NORMAL" ) {
            specializer_state_ = 0;
        }
        else if ( input_state == "SHIELD" ) {
            specializer_state_ = 1;
        }
        else if ( input_state == "SPEED" ) {
            specializer_state_ = 2;
        }
        else if ( input_state == "PROJECTILE" ) {
            specializer_state_ = 3;
        }
        else if ( input_state == "MULTIPLIER" ) {
            specializer_state_ = 4;
        }

        SetSpecializerColor ( specializer_state_ );

    }

    void Player::SetSpecializerColor ( int state ) {
        if ( specializer_state_ == 0 ) {
            // NORMAL - White
            specializer_red_ = 255;
            specializer_green_ = 255;
            specializer_blue_ = 255;
        }
        else if ( specializer_state_ == 1 ) {
            // SHIELD - Green
            specializer_red_ = 255;
            specializer_green_ = 153;
            specializer_blue_ = 76;
        }
        else if ( specializer_state_ == 2 ) {
            // SPEED - Blue
            specializer_red_ = 0;
            specializer_green_ = 0;
            specializer_blue_ = 102;
        }
        else if ( specializer_state_ == 3 ) {
            // PROJECTILE - Yellow
            specializer_red_ = 255;
            specializer_green_ = 255;
            specializer_blue_ = 0;
        }
        else if ( specializer_state_ == 4 ) {
            // MULTIPLIER - Red
            specializer_red_ = 204;
            specializer_green_ = 0;
            specializer_blue_ = 0;
        }
    }

    #pragma endregion



#pragma endregion

#pragma region Accessor

    #pragma region Position Properties

    float Player::X () const {
        return x_;
    }

    float Player::Y () const {
        return y_;
    }

    int Player::Width () const {
        return width_;
    }

    int Player::Height () const {
        return height_;
    }

    bool Player::Inverted() const {
        return inverted_;
    }

    #pragma endregion

    #pragma region Specializer Properties

    int Player::SpecializerRed () const {
        return specializer_red_;
    }

    int Player::SpecializerGreen () const {
        return specializer_green_;
    }

    int Player::SpecializerBlue () const {
        return specializer_blue_;
    }

    string Player::SpecializerState () const {

        string specializer_state = "";

        if ( specializer_state_ == 0 ) {
            specializer_state = "NORMAL";
        }
        else if ( specializer_state_ == 1 ) {
            specializer_state = "SHIELD";
        }
        else if ( specializer_state_ == 2 ) {
            specializer_state = "SPEED";
        }
        else if ( specializer_state_ == 3 ) {
            specializer_state = "PROJECTILE";
        }
        else if ( specializer_state_ == 4 ) {
            specializer_state = "MULTIPLIER";
        }

        return specializer_state;
    }

    #pragma endregion

#pragma endregion

#pragma region Functionality

    #pragma region Movement

        void Player::RightMovement() {
            x_ += speed_;
        }

        void Player::LeftMovement() {
            x_ -= speed_;
        }

        void Player::GravityMovement() {
            if ( inverted_ ) {
                // Upwards
                if ( min( 0.0f, gravity_ ) == 0.0f ) {
                    gravity_ = -gravity_;
                }
                y_ += gravity_;
            }
            else {
                // Downwards
                if ( max( 0.0f, gravity_ ) == 0.0f ) {
                    gravity_ = -gravity_;
                }
                y_ += gravity_;
            }
        }

    #pragma endregion

    #pragma region Within Window Bounds


        bool Player::WithinLeftBounds() {
            if ( x_ - ( width_ / 2 ) > 0 ) {
                return true;
            }
            return false;
        }

        bool Player::withinRightBounds( int width ) {
            if ( x_ + (width_ / 2) < width ) {
                return true;
            }
            return false;
        }

        bool Player::WithinTopBounds() {
            if ( y_ - ( height_ / 2 ) > 0 ) {
                return true;
            }
            return false;
        }

        bool Player::WithinBottomBounds( int height ) {
            if ( y_ + ( height_ / 2 ) < height ) {
                return true;
            }
            return false;
        }

    #pragma endregion


#pragma endregion

解决方案

Your game should have a game loop.

Typically, a (very basic) game loop looks like:

while (playing) {
    accept_input()
    update_game_logic()
    render()
}

Within your update_game_logic() function you would have a section which updates the player's position. The player's position update step will often look like some mixture of:

// 1. sum up forces on the player (i.e. running to the right)
// 2. add current_gravity (normal or inverted)
// 3. check for any collision and add an opposing force 
    // (if touching the ground add a force directly opposite the ground, equal to the force the object is pushing down with)
// 4. resolve position using some form of integration
    // e.g. add force (* deltatime) to acceleration, add acceleration (* deltatime) to velocity, add velocity (* deltatime) to position.

Because you are adjusting the player's position based on forces every tick, you can continue to accept input and render the screen whilst updating the game logic.

这篇关于使用C ++ Win32实现重力翻转力学的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆