|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
نويسنده |
پيغام |
eta مدیر سایت
تاريخ عضويت: 2 شنبه 27 تير 1384 تعداد ارسالها: 2153 محل سكونت: شاهين شهر
جمعه 23 شهريور 1386 - 16:36 |
|
|
اينم قسمت آخر اين آموزشه:
سورس کد به همراه نسخه قابل اجرا
مي تونيد از اين لينک داونلودش کنيد.
اينم يه تصوير از اجراي پروژه.
محدوده آبي مربوط به پس زمينه منوه محدوده قرمز مربوط به پي زمينه زير منوه و دکمه با نوشته سفيد دکمه فعاله. شما مي تونيد با حرکت بر روي دکمه ها دکمه مورد نظرتون رو فعال کنيد. با زدن دکمه شروع بازي رو آغاز کنيد و با فشردن دکمه پايان از بازي خارج بشيد.
دکمه enter هم باعث اجراي فرمان دکمه انتخاب شده ميشه. همه اش همين.
بسم الله!!
تابع start کلاس GameEngine يه فرق کوچولو کرده.
كد: |
void GameEngine::start()
{
for(int i=0 ; i<loops.size() ; i++)
{
while(loops[i]->getGameCommand() != EXIT)
{
if(loops[i]->getGameCommand() == END_LOOP)
break;
loops[i]->handleEvents();
loops[i]->updateGame();
loops[i]->paint(display);
}
if(loops[i]->getGameCommand() == EXIT)
exit(0);
}
} |
بقيه کلاسها عبارتند از:
1ـ Menu
2ـ SubMenu
3ـ MenuElement
4ـ Level1
5ـ Button
کلاس Menu :
کلاس Menu يه GameLoopه که به شما امکان داشتن يه منو رو ميده. قسمت مديريت رويدادهاي منو توي اين ملاس نوشته شده.
منوي ما دوتا دکمه داره شروع و پايان. کد مديريت رويدادهاشون رو مي تونيد توي اين کلاس ببينيد.
اين هدرشه :
كد: |
#include "GameLoop.h"
#include "SubMenu.h"
#include <vector>
using namespace std;
#ifndef MENU_H
#define MENU_H
class Menu : public GameLoop
{
private:
int activeSubMenu;
SDL_Surface* backGround;
vector<SubMenu*> subMenus;
public:
Menu(vector<SubMenu*> subMenus, SDL_Surface* backGround);
~Menu(void);
void handleEvents();
void updateGame();
void paint(SDL_Surface* screen);
};
#endif
|
و اين cpp :
كد: |
#include "Menu.h"
Menu::Menu(vector<SubMenu*> subMenus, SDL_Surface* backGround) : subMenus(subMenus), backGround(backGround)
{
activeSubMenu = 0;
}
Menu::~Menu(void)
{
SDL_FreeSurface(backGround);
}
void Menu::handleEvents()
{
SDL_Event event;
int selection;
while(SDL_PollEvent(&event))
{
switch(event.type)
{
case SDL_MOUSEMOTION:
subMenus[activeSubMenu]->handleMouseMotion(event.motion.x, event.motion.y,
(backGround->w-subMenus[activeSubMenu]->Width())/2,
(backGround->h-subMenus[activeSubMenu]->Height())/2);
break;
case SDL_MOUSEBUTTONDOWN:
selection = subMenus[activeSubMenu]->handleClick(event.button.x, event.button.y,
(backGround->w-subMenus[activeSubMenu]->Width())/2,
(backGround->h-subMenus[activeSubMenu]->Height())/2, event.button.button);
if(selection == 0)
command = END_LOOP;
else if(selection == 1)
command = EXIT;
break;
case SDL_KEYDOWN:
if(event.key.keysym.sym == SDLK_RETURN)
{
selection = subMenus[activeSubMenu]->handleKeyEnter();
if(selection == 0)
command = END_LOOP;
else if(selection == 1)
command = EXIT;
}
break;
case SDL_QUIT:
command = EXIT;
break;
}
}
}
void Menu::updateGame()
{
}
void Menu::paint(SDL_Surface* screen)
{
SDL_BlitSurface(backGround, NULL, screen, NULL);
SubMenu* submenu = subMenus[activeSubMenu];
for(int i=0; i<subMenus.size() ; i++)
subMenus[i]->paint(screen, (backGround->w-submenu->Width())/2,
(backGround->h-submenu->Height())/2);
SDL_Flip(screen);
}
|
تابع paint پس زمينه منو رو مي کشه و بعد به زير منو ميگه تا خودش رو بکشه. لازم به ذکره که افزودن هر گونه جلوه تصويري به سادگي قابل انجامه. مثلا توي همين تابع مي تونيد براي زير منو سايه بزنيد.
کلاس SubMenu :
کلاس SubMenu يه مشت element داره که وظيقه عمومي اش مديريت هموناست. کلاس منو مون براي مديريت رويدادها از روالهاي زير منو استفاده مي کنه. اگه بخوايم ميتونيم از توابع مديريت رويدادهاي element ها هم براي موارد جزئي تر استفاده کنيم.
هدر :
كد: |
#include "MenuElement.h"
#include <vector>
using namespace std;
#ifndef SUBMENU_H
#define SUBMENU_H
enum Click {LEFT, RIGHT};
class SubMenu
{
private:
vector<MenuElement*> elements;
SDL_Surface* workingSurface;
SDL_Surface* backGround;
int activeElement;
public:
SubMenu(vector<MenuElement*> elements, SDL_Surface* backGround);
~SubMenu(void);
int Width();
int Height();
int handleClick(int x, int y, int begX, int begY, int type);
int handleMouseMotion(int x, int y, int begX, int begY);
int handleKeyEnter();
int handlekeyCharacter();
int handleKeyEscape();
void paint(SDL_Surface* screen, int x, int y);
};
#endif
|
cpp :
كد: |
#include "SubMenu.h"
#include "mathutil.h"
#include "SDL_gfxPrimitives.h"
SubMenu::SubMenu(vector<MenuElement*> elements, SDL_Surface* backGround) :
elements(elements), backGround(backGround)
{
activeElement = 0;
for(int i=0; i<elements.size() ; i++)
{
elements[i]->setX((backGround->w - elements[i]->getPicture().w)/2);
elements[i]->setY(((4*backGround->h/5)/(elements.size()+1))*(i+1)+elements[i]->getPicture().h/2);
}
}
SubMenu::~SubMenu(void)
{
SDL_FreeSurface(backGround);
}
int SubMenu::Width()
{
return backGround->w;
}
int SubMenu::Height()
{
return backGround->h;
}
int SubMenu::handleMouseMotion(int x, int y, int begX, int begY)
{
for(int i=0 ; i<elements.size() ; i++)
{
SDL_Rect rect = elements[i]->getPicture().clip_rect;
rect.x = elements[i]->X();
rect.y = elements[i]->Y();
if(isInRect(x-begX, y- begY, rect))
{
activeElement = i;
return i;
}
}
return -1;
}
int SubMenu::handleClick(int x, int y, int begX, int begY, int type)
{
return handleMouseMotion(x, y, begX, begY);
}
int SubMenu::handleKeyEnter()
{
return activeElement;
}
int SubMenu::handlekeyCharacter()
{
return 1;
}
int SubMenu::handleKeyEscape()
{
return 1;
}
void SubMenu::paint(SDL_Surface* screen, int x, int y)
{
SDL_Rect dstRect;
dstRect.x = (screen->w - backGround->w) / 2;
dstRect.y = (screen->h - backGround->h) / 2;
dstRect.w = backGround->w;
dstRect.h = backGround->h;
SDL_BlitSurface(backGround, NULL, screen, &dstRect);
int xl = 0, yl = 0;
for(int i=0; i<elements.size() ; i++)
elements[i]->paint(screen, x+elements[i]->X(), y+elements[i]->Y(), (activeElement == i) ? SELECTED : 0);
// rectangleColor(screen, elements[i]->X()+x, elements[i]->Y()+y, elements[i]->X()+elements[i]->getPicture().w+x, elements[i]->Y()+elements[i]->getPicture().h+y, 0x00ffffff);
}
|
کلاس MenuElemnt :
يه کلاسه که کليه اعضاي زير منو ها از اون ارث مي برن. فعلا به بيش از همين کلاس براي اين دمو نياز نداريم.
هدر :
كد: |
#include "MenuElement.h"
#include <vector>
using namespace std;
#ifndef SUBMENU_H
#define SUBMENU_H
enum Click {LEFT, RIGHT};
class SubMenu
{
private:
vector<MenuElement*> elements;
SDL_Surface* workingSurface;
SDL_Surface* backGround;
int activeElement;
public:
SubMenu(vector<MenuElement*> elements, SDL_Surface* backGround);
~SubMenu(void);
int Width();
int Height();
int handleClick(int x, int y, int begX, int begY, int type);
int handleMouseMotion(int x, int y, int begX, int begY);
int handleKeyEnter();
int handlekeyCharacter();
int handleKeyEscape();
void paint(SDL_Surface* screen, int x, int y);
};
#endif
|
cpp :
كد: |
#include "MenuElement.h"
#include "imageutil.h"
MenuElement::MenuElement(SDL_Surface* picture) : picture(picture)
{
if(picture == NULL)
{
width = 0;
height = 0;
}
else
{
width = picture->w;
height = picture->h;
}
}
MenuElement::~MenuElement(void)
{
SDL_FreeSurface(picture);
SDL_FreeSurface(workingSurface);
}
const SDL_Surface& MenuElement::getPicture()
{
return *picture;
}
void MenuElement::setX(int val)
{
x = val;
}
void MenuElement::setY(int val)
{
y = val;
}
int MenuElement::X()
{
return x;
}
int MenuElement::Y()
{
return y;
}
int MenuElement::handleClick(int x, int y)
{
return 0;
}
int MenuElement::handleKeyEnter()
{
return 0;
}
int MenuElement::handlekeyCharacter()
{
return 0;
}
int MenuElement::handleKeyEscape()
{
return 0;
}
void MenuElement::paint(SDL_Surface* screen, int x, int y, int status)
{
if(width != 0 && height != 0 && screen != NULL)
{
workingSurface = applyEffect(status);
SDL_Rect dstRect;
dstRect.x = x;
dstRect.y = y;
dstRect.w = width;
dstRect.h = height;
SDL_BlitSurface(workingSurface, NULL, screen, &dstRect);
}
}
SDL_Surface* MenuElement::applyEffect(int status)
{
workingSurface = new SDL_Surface(*picture);
if(status&SELECTED)
{
SDL_LockSurface(workingSurface);
Uint32 back = getpixel(workingSurface, 0, 0);
for(int x=0 ; x<workingSurface->w ; x++)
for(int y=0 ; y<workingSurface->h ; y++)
if(getpixel(workingSurface, x, y)!= back)
putpixel(workingSurface, x, y, 0xffffffff);
SDL_UnlockSurface(workingSurface);
}
else
{
SDL_LockSurface(workingSurface);
Uint32 back = getpixel(workingSurface, 0, 0);
for(int x=0 ; x<workingSurface->w ; x++)
for(int y=0 ; y<workingSurface->h ; y++)
if(getpixel(workingSurface, x, y)!= back)
putpixel(workingSurface, x, y, 0x000000ff);
SDL_UnlockSurface(workingSurface);
}
return workingSurface;
}
|
تابع applyEffects يهتابعه که براي افزودن effectها به اعضاي زير منو استفاده ميشه. در حال حاضر تنها effect مورد استفاده تغيير رنگ متن گزينه انتخاب شده است.
کلاس Level1 :
اين کلاس به عنوان مرحله اول بازي انتخاب شده. البته درباره طراحي اش ايجاد يک کلاس براي هر مرحله کار عاقلانه اي نيست ولي براي نشون دادن تاثير فشردن دکمه شروع به طور موقتي مورد استفاده قرار گرفته.
فقط هم رويداد خروج رو مديريت مي کنه.
هدر :
كد: |
#include "SDL.h"
#ifndef LEVEL1_H
#define LEVEL1_H
class Level1 : public GameLoop
{
private:
SDL_Surface* backGround;
public:
Level1(SDL_Surface* backGround) : backGround(backGround) {}
~Level1(void)
{
SDL_FreeSurface(backGround);
}
void handleEvents()
{
SDL_Event event;
while(SDL_PollEvent(&event))
{
switch(event.type)
{
case SDL_QUIT:
command = EXIT;
break;
}
}
}
void updateGame() {}
void paint(SDL_Surface* screen)
{
SDL_BlitSurface(backGround, &(screen->clip_rect), screen, &(backGround->clip_rect));
SDL_Flip(screen);
}
};
#endif
|
کلاس Button :
اين کلاس در حال حاضر بي کاربرده ولي براي نشون دادن چگونگي توسعه انواع اعضاي زير منو نوشته شده.
هدر :
كد: |
#ifndef BUTTON_H
#define BUTTON_H
#include "MenuElement.h"
class Button : public MenuElement
{
public:
Button(SDL_Surface* picture);
~Button(void);
int handleClick(int x, int y);
int handleKeyEnter();
int handlekeyCharacter();
int handleKeyEscape();
void paint(SDL_Surface* screen, int x, int y, int status);
};
#endif
|
cpp :
كد: |
#include "Button.h"
Button::Button(SDL_Surface* picture) : MenuElement (picture)
{
}
Button::~Button(void)
{
}
int Button::handleClick(int x, int y)
{
return 1;
}
int Button::handleKeyEnter()
{
return 1;
}
int Button::handlekeyCharacter()
{
return 1;
}
int Button::handleKeyEscape()
{
return 0;
}
void Button::paint(SDL_Surface* screen, int x, int y, int status)
{
MenuElement::paint(screen, x, y, status);
}
|
ساير سورسها :
فايل main.cpp :
منابع رو لود مي کنه و کلا سيستم رو راه اندازي ميکنه.
كد: |
#include "SDL.h"
#include "GameEngine.h"
#include "Menu.h"
#include "Button.h"
#include <vector>
#include "Level1.h"
#include "SDL_image.h"
using namespace std;
int main(int a, char* b[])
{
Button *start;
Button *end;
SubMenu *mainMenu;
Menu *menu;
Level1 *level1;
vector<MenuElement*> elements;
start = new Button(IMG_Load("start.png"));
elements.push_back(start);
end = new Button(IMG_Load("end.png"));
elements.push_back(end);
vector<SubMenu*> subMenues;
mainMenu = new SubMenu(elements, IMG_Load("menu main.png"));
subMenues.push_back(mainMenu);
vector<GameLoop*> loops;
menu = new Menu(subMenues, IMG_Load("menu back.png"));
loops.push_back(menu);
level1 = new Level1(IMG_Load("level1.png"));
loops.push_back(level1);
GameEngine myGame(loops);
myGame.start();
delete start;
delete mainMenu;
delete menu;
delete level1;
return 0;
}
} |
فايل : mathutil
كد: |
#include "SDL.h"
#ifndef MATHUTIL_H
#define MATHUTIL_H
bool isInRect(int x, int y, const SDL_Rect& rect)
{
if(x>rect.w+rect.x || x<rect.x || y>rect.h+rect.y || y<rect.y)
return false;
return true;
}
#endif
|
فايل imageutil :
اينا دو تابع براي دريافت و تعيين رنگ يک پيکسل هستند. که توي خود راهنماي SDL نوشته شده بودن.
كد: |
#include "SDL.h"
#ifndef IMAGEUTIL_H
#define IMAGEUTIL_H
Uint32 getpixel(SDL_Surface *surface, int x, int y)
{
int bpp = surface->format->BytesPerPixel;
/* Here p is the address to the pixel we want to retrieve */
Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * bpp;
switch(bpp) {
case 1:
return *p;
case 2:
return *(Uint16 *)p;
case 3:
if(SDL_BYTEORDER == SDL_BIG_ENDIAN)
return p[0] << 16 | p[1] << 8 | p[2];
else
return p[0] | p[1] << 8 | p[2] << 16;
case 4:
return *(Uint32 *)p;
default:
return 0; /* shouldn't happen, but avoids warnings */
}
}
/*
* Set the pixel at (myX, myY) to the given myValue
* NOTE: The surface must be locked before calling this!
*/
void putpixel(SDL_Surface *surface, int x, int y, Uint32 pixel)
{
int bpp = surface->format->BytesPerPixel;
/* Here p is the address to the pixel we want to set */
Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * bpp;
switch(bpp) {
case 1:
*p = pixel;
break;
case 2:
*(Uint16 *)p = pixel;
break;
case 3:
if(SDL_BYTEORDER == SDL_BIG_ENDIAN) {
p[0] = (pixel >> 16) & 0xff;
p[1] = (pixel >> 8) & 0xff;
p[2] = pixel & 0xff;
} else {
p[0] = pixel & 0xff;
p[1] = (pixel >> 8) & 0xff;
p[2] = (pixel >> 16) & 0xff;
}
break;
case 4:
*(Uint32 *)p = pixel;
break;
}
}
#endif |
|
_________________ تالار اصول ->صفحه ها، مقالات و تاپیکهای مفید
|
|
بازگشت به بالا |
|
|
|
|
|
|
|
|
صفحه 3 از 7 |
تمام ساعات و تاريخها بر حسب 3.5+ ساعت گرينويچ مي باشد برو به صفحه قبلي 1, 2, 3, 4, 5, 6, 7 بعدي
|
|
شما نمي توانيد در اين انجمن نامه ارسال كنيد. شما نمي توانيد به موضوعات اين انجمن پاسخ دهيد شما نمي توانيد نامه هاي ارسالي خود را در اين انجمن ويرايش كنيد شما نمي توانيد نامه هاي ارسالي خود را در اين انجمن حذف كنيد شما نمي توانيد در نظر سنجي هاي اين انجمن شركت كنيد
|
|
|