简单横版游戏
作业要求
- 左边wasd4个虚拟按键能控制角色移动
- 右边2个虚拟按键x,y能控制角色播放不同的帧动画
- 界面所有字体要求:使用fonts目录下的arial.ttf,字体大小为36
- 角色不会移动到可视窗口外
- 添加倒计时
- 添加人物血条
- X、Y播放的动画不能同时播放
- 点击虚拟按键x播放帧动画并让血条减少,点击y播放帧动画并让血条增加(加分项)
实现效果
具体实现
HelloWorldScene.cpp
#include "HelloWorldScene.h"
#include "SimpleAudioEngine.h"
using namespace std;
#pragma execution_character_set("utf-8")
USING_NS_CC;
Scene* HelloWorld::createScene()
{
return HelloWorld::create();
}
static void problemLoading(const char* filename)
{
printf("Error while loading: %s\n", filename);
printf("Depending on how you compiled you might have to add 'Resources/' in front of filenames in HelloWorldScene.cpp\n");
}
bool HelloWorld::init()
{
if ( !Scene::init() )
{
return false;
}
visibleSize = Director::getInstance()->getVisibleSize();
origin = Director::getInstance()->getVisibleOrigin();
auto texture = Director::getInstance()->getTextureCache()->addImage("$lucia_2.png");
auto frame0 = SpriteFrame::createWithTexture(texture, CC_RECT_PIXELS_TO_POINTS(Rect(0, 0, 113, 113)));
player = Sprite::createWithSpriteFrame(frame0);
player->setPosition(Vec2(origin.x + visibleSize.width / 2,
origin.y + visibleSize.height / 2));
addChild(player, 3);
Sprite* sp0 = Sprite::create("hp.png", CC_RECT_PIXELS_TO_POINTS(Rect(0, 320, 420, 47)));
Sprite* sp = Sprite::create("hp.png", CC_RECT_PIXELS_TO_POINTS(Rect(610, 362, 4, 16)));
pT = ProgressTimer::create(sp);
pT->setScaleX(90);
pT->setAnchorPoint(Vec2(0, 0));
pT->setType(ProgressTimerType::BAR);
pT->setBarChangeRate(Point(1, 0));
pT->setMidpoint(Point(0, 1));
pT->setPercentage(100);
pT->setPosition(Vec2(origin.x + 14 * pT->getContentSize().width, origin.y + visibleSize.height - 2 * pT->getContentSize().height));
addChild(pT, 1);
sp0->setAnchorPoint(Vec2(0, 0));
sp0->setPosition(Vec2(origin.x + pT->getContentSize().width, origin.y + visibleSize.height - sp0->getContentSize().height));
addChild(sp0, 0);
idle.reserve(1);
idle.pushBack(frame0);
attack.reserve(17);
for (int i = 0; i < 17; i++) {
auto frame = SpriteFrame::createWithTexture(texture, CC_RECT_PIXELS_TO_POINTS(Rect(113 * i, 0, 113, 113)));
attack.pushBack(frame);
}
attack.pushBack(frame0);
auto attackAnimation = Animation::createWithSpriteFrames(attack, 0.1f);
AnimationCache::getInstance()->addAnimation(attackAnimation, "attack");
auto texture2 = Director::getInstance()->getTextureCache()->addImage("$lucia_dead.png");
dead.reserve(22);
for (int i = 0; i < 22; i++) {
auto frame = SpriteFrame::createWithTexture(texture2, CC_RECT_PIXELS_TO_POINTS(Rect(79 * i, 0, 79, 90)));
dead.pushBack(frame);
}
dead.pushBack(frame0);
auto deadAnimation = Animation::createWithSpriteFrames(dead, 0.1f);
AnimationCache::getInstance()->addAnimation(deadAnimation, "dead");
auto texture3 = Director::getInstance()->getTextureCache()->addImage("$lucia_forward.png");
run.reserve(8);
for (int i = 0; i < 2; i++) {
auto frame = SpriteFrame::createWithTexture(texture3, CC_RECT_PIXELS_TO_POINTS(Rect(68 * i, 0, 68, 101)));
run.pushBack(frame);
}
run.pushBack(frame0);
auto runAnimation = Animation::createWithSpriteFrames(run, 0.1f);
AnimationCache::getInstance()->addAnimation(runAnimation, "run");
auto menu = Menu::create();
menu->setPosition(80, 50);
addChild(menu);
auto createDirectionLabel = [this, &menu](string c) {
int x = 0, y = 0;
auto label = Label::create(c, "arial", 36);
auto menuItem = MenuItemLabel::create(label, CC_CALLBACK_1(HelloWorld::moveCallback, this, c));
if (c == "W") {
y += 1.2 * label->getContentSize().height;
}
else if (c == "A") {
x -= 1.5 * label->getContentSize().width;
}
else if (c == "D") {
x += 1.5 * label->getContentSize().width;
}
menuItem->setPosition(x, y);
menu->addChild(menuItem);
};
createDirectionLabel("W");
createDirectionLabel("S");
createDirectionLabel("A");
createDirectionLabel("D");
auto labelX = Label::create("X", "fonts/arial.ttf", 36);
auto menuItem = MenuItemLabel::create(labelX, CC_CALLBACK_1(HelloWorld::attackCallback, this));
menuItem->setPosition(origin.x + visibleSize.width - 120, -15);
menu->addChild(menuItem);
auto labelY = Label::create("Y", "fonts/arial.ttf", 36);
menuItem = MenuItemLabel::create(labelY, CC_CALLBACK_1(HelloWorld::deadCallback, this));
menuItem->setPosition(origin.x + visibleSize.width - 100, 15);
menu->addChild(menuItem);
time = Label::createWithTTF("180", "fonts/arial.ttf", 36);
time->setPosition(origin.x + visibleSize.width / 2, origin.y + visibleSize.height -50);
addChild(time);
schedule(schedule_selector(HelloWorld::update), 1.0f);
return true;
}
void HelloWorld::moveCallback(Ref* pSender, string direction)
{
auto position = player->getPosition();
if (isAnimating == false && ((position.x > 50 && direction == "A") || (position.x < visibleSize.width-50 && direction == "D") || (position.y > 50 && direction == "S") || (position.y < visibleSize.height-50 && direction == "W"))) {
isAnimating = true;
int x, y;
if (direction == "W") {
x = 0;
y = 50;
}
else if (direction == "A") {
x = -50;
y = 0;
}
else if (direction == "S") {
x = 0;
y = -50;
}
else if (direction == "D") {
x = 50;
y = 0;
}
auto spawn = Spawn::createWithTwoActions(Animate::create(AnimationCache::getInstance()->getAnimation("run")), MoveBy::create(0.5f, Vec2(x, y)));
auto sequence = Sequence::create(spawn, CCCallFunc::create(([this]() { isAnimating = false; })), nullptr);
player->runAction(sequence);
}
return;
}
void HelloWorld::attackCallback(Ref * pSender)
{
if (isAnimating == false) {
isAnimating = true;
auto sequence = Sequence::create(Animate::create(AnimationCache::getInstance()->getAnimation("attack")),
CCCallFunc::create(([this]() {
isAnimating = false;
})), nullptr);
player->runAction(sequence);
float percentage = pT->getPercentage();
if (percentage < 100) {
auto to = ProgressFromTo::create(1.0f, percentage, percentage + 20);
pT->runAction(to);
}
}
}
void HelloWorld::deadCallback(Ref * pSender)
{
if (isAnimating == false) {
isAnimating = true;
auto sequence = Sequence::create(Animate::create(AnimationCache::getInstance()->getAnimation("dead")),
CCCallFunc::create(([this]() {
isAnimating = false;
})), nullptr);
player->runAction(sequence);
float percentage = pT->getPercentage();
if (percentage > 0) {
auto to = ProgressFromTo::create(2.0f, percentage, percentage - 20);
pT->runAction(to);
}
}
}
void HelloWorld::update(float dt)
{
string str = time->getString();
int timeLength = atoi(str.c_str());
if (timeLength > 0) {
timeLength--;
CCString* ns = CCString::createWithFormat("%d", timeLength);
string s = ns->_string;
time->setString(s);
}
else {
unschedule(schedule_selector(HelloWorld::update));
}
}
HelloWorldScene.h
using namespace cocos2d;
class HelloWorld : public cocos2d::Scene
{
public:
static cocos2d::Scene* createScene();
virtual bool init();
// implement the "static create()" method manually
CREATE_FUNC(HelloWorld);
private:
cocos2d::Sprite* player;
cocos2d::Vector<SpriteFrame*> attack;
cocos2d::Vector<SpriteFrame*> dead;
cocos2d::Vector<SpriteFrame*> run;
cocos2d::Vector<SpriteFrame*> idle;
cocos2d::Size visibleSize;
cocos2d::Vec2 origin;
cocos2d::Label* time;
int dtime;
cocos2d::ProgressTimer* pT;
//判断是否在播放动作
bool isAnimating;
//移动
void moveCallback(Ref* pSender, std::string direction);
//攻击
void attackCallback(Ref* pSender);
//死亡
void deadCallback(Ref* pSender);
//重写update,实现倒计时
void update(float time)override;
};
视频演示以及资源
视频演示以及资源