wxWidgets学习 - 弹球程序

学习了几天的wx了,作为练习,做了一个程序:随机生成多个小球在窗口内随机方向运动,并且小球碰到屏幕可以反弹。

代码如下,为了方便所有的代码都写在了一个文件中了

main.cpp:
#include <wx/wx.h>
#include <ctime>
#include <cstdlib>

//弹球
typedef struct
{
    wxCoord x, y;    //位置
    wxCoord r;       //半径
    wxCoord dx, dy;  //运动增量
    wxColour colour;
}Pinball;

//随机产生一个(minN, maxN]范围的整数
int RandNumber(int minN, int maxN)
{
    return minN + rand() % (maxN - minN);
}

//主窗口类
class MyFrame: public wxFrame
{
public:
    MyFrame();
    ~MyFrame();

protected:
    //事件处理函数
    void OnPaint(wxPaintEvent &event);
    void OnTimer(wxTimerEvent &event);
    void OnPause(wxCommandEvent &event);
    void OnResume(wxCommandEvent &event);
    void OnRestart(wxCommandEvent &event);
    void OnAbout(wxCommandEvent &event);

    //普通函数
    void PaintBalls();

    //声明事件处理表
    wxDECLARE_EVENT_TABLE();

private:
    //控件ID定义
    enum{
        wxIDT_TIEMER = 1000,
        wxIDM_PAUSE,
        wxIDM_RESUME,
        wxIDM_RESTART,
    };

    //成员变量
    int ballCnt;
    Pinball *pballs;
    wxTimer *timer;
    wxBitmap bitmap;
    wxMemoryDC memDC;
};

//定义事件处理表
wxBEGIN_EVENT_TABLE(MyFrame, wxFrame)
    EVT_PAINT(OnPaint)
    EVT_TIMER(wxIDT_TIEMER, MyFrame::OnTimer)
    EVT_MENU(wxIDM_PAUSE, MyFrame::OnPause)
    EVT_MENU(wxIDM_RESUME, MyFrame::OnResume)
    EVT_MENU(wxIDM_RESTART, MyFrame::OnRestart)
    EVT_MENU(wxID_ABOUT, MyFrame::OnAbout)
wxEND_EVENT_TABLE()

MyFrame::MyFrame()
        :wxFrame(NULL, wxID_ANY, wxT("弹球"), wxDefaultPosition, wxDefaultSize,
                 wxDEFAULT_FRAME_STYLE | wxMAXIMIZE)
{
    //设置窗口UI
    SetBackgroundColour(wxColour(0xf9f9f9));
    wxMenu *menuCtrl = new wxMenu;
    menuCtrl->Append(wxIDM_PAUSE, wxT("&暂停\tCtrl-P"));
    menuCtrl->Append(wxIDM_RESUME, wxT("&继续\tCtrl-R"));
    menuCtrl->Append(wxIDM_RESTART, wxT("&重新开始\tCtrl-T"));
    menuCtrl->Append(wxID_EXIT);
    wxMenu *menuHelp = new wxMenu;
    menuHelp->Append(wxID_ABOUT);
    wxMenuBar *menuBar = new wxMenuBar;
    menuBar->Append(menuCtrl, wxT("&控制"));
    menuBar->Append(menuHelp, wxT("&帮助"));
    SetMenuBar(menuBar);

    //初始化成员变量
    ballCnt = RandNumber(10, 30);
    pballs = new Pinball[ballCnt];

    wxRect rect = GetRect();
    bitmap.Create(rect.GetWidth(), rect.GetHeight());
    memDC.SelectObject(bitmap);
    memDC.SetBackground(wxBrush(wxColour(0xf9f9f9)));
    wxPen pen(wxColour(128, 128, 128, 32));
    memDC.SetPen(pen);

    timer = new wxTimer(this, wxIDT_TIEMER);
    wxCommandEvent e;
    OnRestart(e);
}

MyFrame::~MyFrame()
{
    delete[] pballs;
    delete timer;
}

//画出所有弹球(双缓冲避免闪烁问题)
void MyFrame::PaintBalls()
{
    wxRect rect = GetRect();

    //在内存DC画图
    memDC.Clear();
    for (int i = 0; i < ballCnt; ++ i) {
        Pinball *ball = &pballs[i];
        wxBrush brush(ball->colour);
        memDC.SetBrush(brush);
        memDC.DrawCircle(ball->x, ball->y, ball->r);
    }

    //复制到客户区DC
    wxClientDC dc(this);
    dc.Blit(0, 0, rect.GetWidth(), rect.GetHeight(), &memDC, 0, 0);
}

//重绘事件处理
void MyFrame::OnPaint(wxPaintEvent &event)
{
    PaintBalls();
}

//定时器事件处理
void MyFrame::OnTimer(wxTimerEvent &event)
{
    wxRect rect = GetRect();
    Pinball *ball;
    for (int i = 0; i < ballCnt; ++ i) {
        ball = &pballs[i];
        ball->x += ball->dx;
        ball->y += ball->dy;
        if (ball->x - ball->r <= rect.GetLeft() || ball->x + ball->r >= rect.GetRight()) {
            ball->dx = - ball->dx;
        }
        if (ball->y - ball->r <= rect.GetTop() || ball->y + ball->r >= rect.GetBottom()) {
            ball->dy = - ball->dy;
        }
    }
    PaintBalls();
}

//菜单暂停事件
void MyFrame::OnPause(wxCommandEvent &event)
{
    if (timer->IsRunning()) {
        timer->Stop();
    }
}

//菜单恢复事件
void MyFrame::OnResume(wxCommandEvent &event)
{
    if (!timer->IsRunning()) {
        timer->Start();
    }
}

//菜单重新开始事件
void MyFrame::OnRestart(wxCommandEvent &event)
{
    wxRect rect = GetRect();
    for (int i = 0; i < ballCnt; ++ i) {
        Pinball *ball = &pballs[i];
        ball->r = RandNumber(15, 50);
        ball->x = RandNumber(ball->r, rect.GetWidth() - ball->r);
        ball->y = RandNumber(ball->r, rect.GetHeight() - ball->r);
        ball->dx = ball->dy = 0;
        while (!ball->dx && !ball->dy) {
            ball->dx = RandNumber(-8, 8);
            ball->dy = RandNumber(-8, 8);
        }
        ball->colour = wxColour(RandNumber(0x40, 0xff),
                                RandNumber(0x40, 0xff),
                                RandNumber(0x40, 0xff),
                                RandNumber(0x0a, 0xff));
    }
    timer->Start(10);
}

//菜单关于事件
void MyFrame::OnAbout(wxCommandEvent& event)
{
    wxMessageBox(wxT("作者:luoluolzb\r\n时间:2017-12-7"),
                 wxT("帮助"),
                 wxOK | wxICON_INFORMATION);
}

//应用类
class MyApp: public wxApp
{
public:
    virtual bool OnInit();
};

//自动实例化MyApp对象并赋值给全局变量wxTheApp
DECLARE_APP(MyApp)
//声明可以使用wxGetApp()获取实例对象
IMPLEMENT_APP(MyApp)

//入口函数
bool MyApp::OnInit()
{
    srand(time(NULL));  //初始化随机数种子
    MyFrame *frame = new MyFrame();
    frame->Show();
    return true;
}

这里写图片描述

展开阅读全文
©️2020 CSDN 皮肤主题: 大白 设计师: CSDN官方博客 返回首页
实付0元
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值