When my character (flappy bird) contacts obstacles, it shall turns to a gameover scene. The problem is yes it shows up a gameover scene but same time appears the
0x0FBE9B95 (libcocos2d_2015.dll) 中 (於 FlappyBird.exe) 擲回例外狀況: 0xC0000005: 讀取位置 0x00000034 時發生存取違規。
To translate:
0x0FBE9B95 in (libcocos2d_2015.dll) (under FlappyBird.exe) throws an exception 0xC0000005: Access violation writing location 0x00000034.
However, when I hide out all the background stuff as well as _scheduleUpdate()_
, the exception disappears! (Also nothing comes up to the scene...but know that the physics is still here, my flappy bird can fall to ground and turn to gameover scene)
Here is my program:
(GameScene.cpp)
#include "GameScene.h"
#include "GameOverScene.h"
#include "cocostudio/CocoStudio.h"
#include "ui/CocosGUI.h"
#include "Defination.h"
USING_NS_CC;
using namespace cocostudio::timeline;
Scene* GameScene::createScene()
{
// 'scene' is an autorelease object
auto scene = Scene::createWithPhysics();
scene->getPhysicsWorld()->setDebugDrawMask(PhysicsWorld::DEBUGDRAW_ALL);
// 'layer' is an autorelease object
auto layer = GameScene::create();
layer->setPhysicsWorld(scene->getPhysicsWorld());
// add layer as a child to scene
scene->addChild(layer);
// return the scene
return scene;
}
// on "init" you need to initialize your instance
bool GameScene::init()
{
//////////////////////////////
// 1. super init first
if ( !Layer::init() )
{
return false;
}
auto visibleSize = Director::getInstance()->getVisibleSize();
auto origin = Director::getInstance()->getVisibleOrigin();
/*Set screen boundary so that characters will not move outside screen*/
auto edgeBody = PhysicsBody::createEdgeBox(visibleSize,
PHYSICSBODY_MATERIAL_DEFAULT, 3);
edgeBody->setCollisionBitmask(OBSTACLE_COLLISION_BITMASK);
edgeBody->setContactTestBitmask(true);
auto edgeNode = Node::create();
edgeNode->setPhysicsBody(edgeBody);
edgeNode->setPosition(Point(visibleSize.width / 2 + origin.x,
visibleSize.height / 2 + origin.y));
this->addChild(edgeNode);
/*BG*/
bgLayer = Layer::create();
bgTotalWidth = 0;
auto sprite = Sprite::create("bg1.png");
float bgScale = visibleSize.height / sprite->getContentSize().height;
float bgWidth = sprite->getContentSize().width * bgScale;
sprite->release();
allSpriteScale = bgScale;
while (bgTotalWidth < visibleSize.width + bgWidth) {
auto bgSprite = Sprite::create("bg1.png");
bgSprite->setAnchorPoint(Vec2(0, 0));
bgSprite->setPosition(Point(origin.x + bgTotalWidth, origin.y));
bgSprite->setScale(bgScale);
auto scrollAction = RepeatForever::create(MoveBy::create(1, Vec2(-
BACKGROUND_MOVE_SPEED, 0)));
bgSprite->runAction(scrollAction);
bgLayer->addChild(bgSprite);
bgTotalWidth += bgWidth;
}
this->addChild(bgLayer, 0);
/*Pipe*/
pipe = Pipe::Pipe(allSpriteScale);
pipeLayer = Layer::create();
this->addChild(pipeLayer, 1);
/*Flappy Bird*/
playerLayer = Layer::create();
this->addChild(playerLayer, 2);
bird = &FlappyBird::FlappyBird(allSpriteScale, playerLayer);
/*Scheduler*/
scheduleUpdate(); //Enable update
schedule(schedule_selector(GameScene::spawnPipe), PIPE_SPAWN_INTERVAL);
auto collisionListener = EventListenerPhysicsContact::create();
collisionListener->onContactBegin =
CC_CALLBACK_1(GameScene::onContactBegin, this);
Director::getInstance()->getEventDispatcher()-
>addEventListenerWithSceneGraphPriority(collisionListener, this);
return true;
}
void GameScene::update(float delta) {
/*BG Update*/
for each (Sprite* sp in bgLayer->getChildren())
{
if (sp->getPositionX() <= -(sp->getContentSize().width * sp-
>getScaleX())) {
sp->setPosition(Point(bgTotalWidth + sp->getPositionX(), 0));
break;
}
}
}
void GameScene::spawnPipe(float delta) {
pipe.Spawn(pipeLayer);
}
bool GameScene::onContactBegin(PhysicsContact &contact)
{
PhysicsBody* a = contact.getShapeA()->getBody();
PhysicsBody* b = contact.getShapeB()->getBody();
if ( (a->getCollisionBitmask() == FLAPPYBIRD_COLLISION_BITMASK && b-
>getCollisionBitmask() == OBSTACLE_COLLISION_BITMASK) ||
(b->getCollisionBitmask() == FLAPPYBIRD_COLLISION_BITMASK && a-
>getCollisionBitmask() == OBSTACLE_COLLISION_BITMASK)
)
{
auto gameoverScene = GameOverScene::createScene();
Director::getInstance()-
>replaceScene(TransitionFade::create(SCENE_TRANSITION_DURATION,
gameoverScene));
}
return true;
}
The crush line indicated by Visual Studio is in main.cpp:
int APIENTRY _tWinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
// create the application instance
AppDelegate app;
return Application::getInstance()->run(); // Crush here
}
One more interesting thing, I could hardly change my code! In _init()_
, if I just hide out the 2 lines defining my background sprites actions (logically that would not affect others), the exception will come up in my GameScene!
It is very very weird......hope someone can help me out. :(
Remove sprite->release()
, this line causes the exception. Sprite class is already an auto-release object and registered in the auto-release pool once it is spawned.
So, when calling replaceScene()
, all objects shall not be called will be released. However, it cannot reference the sprite in auto-release pool because it was already released by the line sprite->release()
and caused error.
User contributions licensed under CC BY-SA 3.0