I am trying to create a simple platformer game in C++ with SDL, although am having trouble implementing animated sprites into the game. Linked is my git repo.
As you will see i'm currently having difficult trying to draw a single portion of the sprite sheet as the player sprite and looping through it to animate it. At the moment the entire sprite sheet that contains the player sprites is being squished into a 32 pixel rectangle. I have looked into SDL_RenderCopy although changing the variables that I pass to the method has no affect.
https://github.com/mountainfolks/Platformer_SDL
Have you stepped through your code to see which draw call you're hitting? AnimatedSprite inherits from Sprite, but you don't have Draw set as virtual in the base class, so you're actually calling Sprite::Draw. That would explain the behavior that points to the source rectangle being null.
Related
i've tried to make a project, but i can't draw a sprite as i want. I mean that everything works when i just draw a sprite, but it stop working when i am trying to draw the sprite by clicking left mouse button. There's code i tried:
if(zdarzenie.type == Event::MouseButtonPressed && zdarzenie.mouseButton.button == Mouse::Left)
{
pocisk.setPosition(10, 10);
oknoAplikacji.draw(pocisk);
}
Btw, I am writing in Polish as if it would change something.
And yes, i have everything good besides that.
(and i am using 2.4.1 version of SFML)
I don't know what you are doing now because you didn't provide enough of your code and I actually don't understand your if statement but, it can just be :
if (sf::Mouse::isButtonPressed(sf::Mouse::Left))
{
sprite.setPosition(sf::Mouse::getPosition());
renderTarget.draw(sprite);
}
By the way I strongly suggest that you do not use the draw function here but organize your code to have a draw method called in a render loop, because depending on where your code is in your program, the sprite could be drawn for only one frame and then erased since it's not updated.
From what I understand in your code in Polish, you have the right code to do what you want, but the problem comes from the fact that you draw the sprite only once.
The draw method is called every frame and it will erase everything on screen and then redraw them. Doing it only once, like in your code, will only draw it a single time then delete it the very next frame.
At that point multiple solution can be used. If its a GameObject clicking can activate the object to then draw it or a simple bool could be used has a switch in your draw to make it appear.
Here is the setup. I have a orthogonal tile map made with Tiled. There are 5 layers. The bottom 4 comprise the background, while the top layer is the foreground that I will refer to as the “tree” layer. I have a hero sprite that I have added as a child of the tile map at the same node zorder as the tree layer.
The issue that invariably comes up with this scenario is that I want my hero to be in front of trees that he is “below”, but behind those trees that he is “above”. Below and above are determined by the Y coordinate of the hero versus the Y coordinate of any given tree.
The Cocos2d programming guide contains a section for tile maps, and in that section it specifically discusses how to achieve the affect I have described. This information can be found here.
http://www.cocos2d-iphone.org/wiki/doku.php/prog_guide:tiled_maps
The solution is pretty simple. Enable the depth buffer in my code. Add a cc_vertexz property with a value of -1000 to each layer that the hero will be above. Then add a cc_vertexz property to the tree layer with a value of “automatic” as well as a cc_alpha_func property with a value of .5. Then as your hero moves re-adjust its sprite’s vertexz value based on its position within the map.
I did all this and it worked great. However, a problem appeared as soon as I added other “enemy” sprites to this map. As with the hero sprite these sprites were added to the map with the same node zorder as the tree layer, and they too have their vertexz values changed based on their Y coordinate within the map. It should be noted that the hero sprite is added after the enemy sprites. In addition, both the hero and enemy sprites are animated and their textures are not part of the tile map textures. Based on the Cocos2d documentation this should not matter.
The problem is this. If my hero is below an enemy sprite on the map then everything looks and works fine. However, if my hero is above an enemy sprite on the map then as the enemy passes over the hero sprite the background comes through rather than the hero sprite. The best way to describe it is to say that as soon as the enemy sprite begins to pass over the hero sprite, the transparent areas of the enemy sprite begin to fill with the background and the hero sprite is partially obscured until then enemy sprite moves off the hero. It is like the hero sprite is not there.
I know this is related to the order that the sprites are added to the map, because if I change this and have the hero sprite added to the map before the enemy sprites, then the effect reverses in that the background comes through the transparent areas of the hero sprite rather than the enemy sprites. It is almost like the vertexz property is not absolutely determining the order that things are drawn.
Looking into this it appears to be a blending issue and I found what seems to be the solution, which is to subclass the CCSprite class and override the draw method with the following:
-(void) draw {
glEnable(GL_ALPHA_TEST);
glAlphaFunc( GL_GREATER, 0 );
[super draw];
glDisable(GL_ALPHA_TEST);
}
The problem however is that this code is not applicable to the version of Cocos2d that I use, which is Cocos2d 2.1. In addition this appears to be handled by the CCTMXLayer drawing function if automatic vertexz is enabled. As such I do not know if subclassing CCSprite would just be redundant. See below for how CCTMXLayer handles this:
// CCTMXLayer drawing function -(void) draw
{
if( useAutomaticVertexZ_ ) {
glEnable(GL_ALPHA_TEST);
glAlphaFunc(GL_GREATER, alphaFuncValue_);
}
[super draw];
if( useAutomaticVertexZ_ )
glDisable(GL_ALPHA_TEST);
}
I am not new to Cocos2d, but I am very new to anything related to OpenGL. So in short, is the solution just to subclass CCSprite and find the Cocos2d 2.1 equivalent to the above code snippet, or am I simply doing something wrong? I suspect the latter.
Any help would be very much appreciated. Thanks!
This has been resolved. The solution was to use the following on my sprites or sprite sheets as the case may be:
mySprite.shaderProgram = [[CCShaderCache sharedShaderCache]programForKey:kCCShader_PositionTextureColorAlphaTest];
This essentially takes the place of sub-classing CCSprite and overriding the draw method, which is the prescribed method for Cocos2d 1.x, whereas I am using Cocos2d 2.x.
I was wondering if there is a way to draw a gl::texture file with out having to use the gl::draw command every loop. Is there a way I can draw it once, and then not worry about it.
Drawing the image on every loop of draw() is slowing down my application, so I'd like to only draw things once on the screen and then update them if need be.
Quoting from Cinder's tutorials:
"When you create a new Cinder project, you will notice there are a few functions declared for you. Every Cinder project is made up of three main functions. You initialize your variables in the setup() method which is called once when your program begins. You make changes to those variables in the update() method. And finally, you draw() content in your program window. Update and draw are the heartbeat of any Cinder project. UpdateSetup, then update and draw, update and draw, update and draw, on and on until you quit the application."
There's a way though to draw objects permanently in OpenGL and concequently in Cinder but I wouldn't recommend it. Is to disable gl::clear() in your draw function. You can't though selectively delete any unneeded object. You will have to render your scene from scratch. Think of OpenGL's frame-buffer more of a canvas. Everytime you call gl::clear() you take the brush and you paint your canvas black or what ever color you specify with gl::clear(). After that the frame-buffer is "tabula rasa" you have to draw everything you want to display from scratch. If you don't state any gl::clear() command when you draw a new object is like your canvas stays intact and you draw your object on top of the already drawn.
I am building a board game in SDL and here is the problem I am currently facing.
I have a pawn on square 1 and I roll the dice. Based on the value I get on the dice the pawn moves to another square. I am bale to move the pawn after i read the SDL tutorials online. But the problem I am facing is that after moving the pawn to a new location the old pawn still stays at the old location. The tutorials I found on the internet moves a dot but also refreshes the background to cover up the old dot. But I cant do that as my game board is intricate and there are pawns from other players sitting there.
Is there a way in SDL that I could really move a pawn instead of having to create a new pawn at the new location and covering up the old pawn?
The fundamental concept of sprites: Before you insert the sprite, you save a copy of the original screen content. When you need to remove the sprite, you just paste the stored old content back in.
You will have to process all your objects in the correct order (LIFO) for this to work. Since you'll usually be double-buffered, this happens on the cold buffer, so this isn't an issue.
No, your code will need to be able to redraw that board position with the pawn missing. There isn't any way for the computer to automatically reconstruct what the board should look like without the pawn.
It sounds like your render code is mixed in with your game logic. You ought to separate rendering so that you can redraw the complete game scene with a single function call, which you can then use whenever a visible change is made to the game state.
In the isometric tiled map z-ordering example for cocos2d-iphone, they use an object that is already in the tilemap as the player sprite, which is rendered as moving through the trees.
Is there a way to use a random CCNode, created though code (not in the tmx file, and not part of the sprite sheet), and have it z-ordered correctly with the tilemap? addChild is not supported on a CCTMXLayer, and the gives an error when using that reads:'addChild: is not supported on CCTMXLayer. Instead use setTileGID:at:/tileAt:'.
There's got to be a way to have a CCNode (let's say a simple CCSprite) z-order correctly with a tilemap, either using cocos2d's API, or some z-buffer technique. Any pointers?
The CCTMXLayer doesn't support adding tiles at runtime because it's implemented with all sprites on a single spritesheet. Because of this implementation detail you also can't call setTexture on an individual tile.
The easiest solution would be to have the sprite you want to use on the spritesheet at the beginning. If you can't do this because it's generated at runtime or something, the next best thing (without touching cocos2d code) would be to modify the spritesheet.
Put a dummy tile in the spritesheet you're using for the TMXLayer and then, once you have the image you want to use, write it to the spritesheet using CCRenderTexture or something and use the newly generated Texture as your TMXLayer's texture.
You could also modify the CCTMXLayer to allow for your functionality but it sounds like you want to avoid that.
If you want to add a tile to say tile (x,y) ( (x,y) in Tiled Map editor coordinates ) then use the following code -
myTileMap is the reference to the CCTMXTiledMap object.
CCTMXLayer *layer=[myTileMap layerNamed:#"yourlayer"];
NSAssert(floorLayer !=nil, #"Ground layer not found!");
CGPoint tileAddPosition = [layer positionAt: CGPointMake(x,y)];
//Create your CCNode or CCSprite or whatever...say object name is **tileToBeAdded**
tileToBeAdded.anchorPoint = CGPointZero;
tileToBeAdded.position = tileAddPosition;
[myTileMap addChild:addedTile z:1];