Adding scores to game using cocos2d-x - cocos2d-x

I am creating a game in cocos2d-x and i am trying to add scores in my game. First i declared a score variable and set the value to 0. in Bool function using do while loop increased the value by 1, and using printf I displayed the score but it is not working.Please help me with some code.
Int score;
socre=0
do
{
printf("%d",score);
}while(score>=0)

If you are wanting to display your score graphically on a Layer
make a cocos2d::Label, see the documentation.
set its value: label->setString(std::to_string(score));
addChild(label, 1); in your Layer code where it makes sense.
label->setPosition(...)
There are a number of Label types and constructors that you can use, look up what you might want to use: http://www.cocos2d-x.org/reference/native-cpp/V3.0/db/de4/classcocos2d_1_1_label.html
Here is a simple example using one of the provided constructors:
cocos2d::LabelBMFont* label = cocos2d::LabelBMFont::create(std::to_string(score), "Marker Felt");
label->setAlignment(cocos2d::TextHAlignment::CENTER);
addChild(label, 0);
label->setPosition(...);
When you need to update the score, as it changes, use something like:
_label->setString(std::to_string(score));

Related

Best and most performant implementation of dynamic shapes in cesium

I am currently working an application that is using a Cesium Viewer. I need to be able to display a collection of shapes that will be updated dynamically. I am having trouble understanding the best way to do this.
I currently am using Entities and using CallbackProperties to allow for the updating of shapes.
You can through this into a sandcastle to get an idea of how I am doing this. There is a polygon object that is being used as the basis for the cesiumCallback, and it is getting edited by another piece of code. (simulated with the setTimeout)
var viewer = new Cesium.Viewer('cesiumContainer', {});
var polygon = {};
polygon.coordinates = [
{longitude: 0, latitude: 0, altitude: 0},
{longitude: 10, latitude: 10, altitude: 0},
{longitude: 10, latitude: 0, altitude: 0}
];
// converts generic style options to cesium one (aka color -> material)
var polOpts = {};
// function for getting location
polOpts.hierarchy = new Cesium.CallbackProperty(function() {
var hierarchy = [];
for (var i = 0; i < polygon.coordinates.length; i++) {
var coordinate = polygon.coordinates[i];
hierarchy.push(Cesium.Cartesian3.fromDegrees(coordinate.longitude, coordinate.latitude, coordinate.altitude));
}
return hierarchy;
}, false);
viewer.entities.add({polygon: polOpts});
setInterval(function(polygon){
polygon.coordinates[0].longitude--;
}.bind(this, polygon), 1000);
The polygon being passed in is a class that generically describes a polygon, so it has an array of coordinates and style options, as well as a render method that calls this method renderPolygon passing in itself.
This method of rendering shapes works for everything I need it to, but it is not very performant. There are two cases for shapes updating, one type of shape will be updated over a long period of time, as a slow rate like once every few seconds. The other is shapes that will will get updated many times, like thousands, in a few seconds, then not change again for a long time, if ever.
I had two ideas for how to fix this.
Idea 1:
Have two methods, a renderDynamicPolygon and a renderStaticPolygon.
The renderDynamicPolygon method would do the above functionality, using the cesiumCallbackProperties. This would be used for shapes that are getting updated many times during the short time they are being updated.
The renderStaticPolygon method would replace the entities properties that are using callbackProperties with constant values, once the updating is done.
This creates a lot of other work to make sure shapes are in the right state, and doesn't help the shapes that are being updated slowly over a long period of time.
Idea 2:
Similarly to how the primitives work, I tried removing the old entity and adding it again with its updated properties each time its need to be updated, but this resulted in flickering, and unlike primitives, i could not find a async property for entities.
I also tried using primitives. It worked great for polylines, I would simply remove the old one and add a new one with the updated properties. I was also using the async = false to ensure there was no flickering. This issue I ran into here was not all shapes can be created using primitives. (Is this true?)
The other thing I tried was using the geometry instance using the geometry and appearance. After going through the tutorial on the cesium website I was able to render a few shapes, and could update the appearance, but found it close to impossible to figure out how to update the shapes correctly, and also have a very hard time getting them to look correct. Shapes need to have the right shape, a fill color and opacity and a stroke color, opacity and weight. I tried to use the polygonOutlineGeometry, but had not luck.
What would be the best way to implement this? Are one of these options headed the right way or is there some other method of doing this I have not uncovered yet?
[Edit] I added an answer of where I have gotten, but still not complete and looking for answers.
I have came up with a pretty good solution to this, but it still has one small issue.
I made too ways of showing entities. I am calling one render and one paint. Render uses the the Cesium.CallbackProperty with the isConstant property true, and paint with the isConstantProperty false.
Then I created a function to change the an entity from render to paint and vice vera. It goes through the entities callback properties an uses the setCallback property to overwrite the property with a the correct function and isConstant value.
Example:
I create a ellipse based on a circle object I have defined.
// isConst is True if it is being "painted" and false if it is being "rendered"
ellipse: lenz.util.extend(this._getStyleOptions(circle), {
semiMinorAxis: new Cesium.CallbackProperty(
this._getRadius.bind(this, circle),
isConst
),
semiMajorAxis: new Cesium.CallbackProperty(
this._getRadius.bind(this, circle),
isConst
),
})
So when the shape is being updated (while the user is drawing a shape) the shape is rendered with the isConstant being false.
Then when the drawing is complete it is converted to the painted version using some code like this:
existingEntity.ellipse.semiMinorAxis.setCallback(
this._getRadius.bind(this, circle),
isConst
);
existingEntity.ellipse.semiMajorAxis.setCallback(
this._getRadius.bind(this, circle, 1),
isConst
);
This works great performance wise. I am able to draw hundreds of shapes without the frame dropping much at all. I have attached a screen shot of the cesium map with 612 entities before and after my changes, the frame rate is in the upper right using the chrome render tool.
Before: Locked up at fps 0.9
Note: I redacted the rest of the ui, witch makes the globe look cut off, sorry
And after the changes: The fps remains at 59.9, almost perfect!
Whenever the entity is 'converted' from using constant to not constant callback properties, it and all other entities of the same type flash off then on again. I cannot find a better way to do this conversion. I feel as thought there must still be some thing I am missing.
You could try using a PositionPropertyArray as the polygon's hierarchy with SampledPositionProperty for any dynamic positions and ConstantPositionProperty for any static positions. I'm not sure if it would perform any better than your solution, but it might be worth testing. Here is an example of how it might work that you can paste into the Cesium Sandcastle:
var viewer = new Cesium.Viewer('cesiumContainer', {});
// required if you want no interpolation of position between times
var noInterpolation = {
type: 'No Interpolation',
getRequiredDataPoints: function (degree) {
return 2;
},
interpolateOrderZero: function (x, xTable, yTable, yStride, result) {
if (!Cesium.defined(result)) {
result = new Array(yStride);
}
for (var i = 0; i < yStride; i++) {
result[i] = yTable[i];
}
return result;
}
};
var start = viewer.clock.currentTime;
// set up the sampled position property
var sampledPositionProperty = new Cesium.SampledPositionProperty();
sampledPositionProperty.forwardExtrapolationType = Cesium.ExtrapolationType.HOLD;
sampledPositionProperty.addSample(start, new Cesium.Cartesian3.fromDegrees(0, 0)); // initial position
sampledPositionProperty.setInterpolationOptions({
interpolationAlgorithm: noInterpolation
});
// set up the sampled position property array
var positions = [
sampledPositionProperty,
new Cesium.ConstantPositionProperty(new Cesium.Cartesian3.fromDegrees(10, 10)),
new Cesium.ConstantPositionProperty(new Cesium.Cartesian3.fromDegrees(10, 0))
];
// add the polygon to Cesium viewer
var polygonEntity = new Cesium.Entity({
polygon: {
hierarchy: new Cesium.PositionPropertyArray(positions)
}
});
viewer.zoomTo(viewer.entities.add(polygonEntity));
// add a sample every second
var counter = 1;
setInterval(function(positionArray) {
var time = new Cesium.JulianDate.addSeconds(start, counter, new Cesium.JulianDate());
var position = new Cesium.Cartesian3.fromDegrees(-counter, 0);
positionArray[0].addSample(time, position);
counter++;
}.bind(this, positions), 1000);
One nice thing about this is you can set the timeline start/end time to a reasonable range and use it to see your polygon at any time within the sample range so you can see the history of your polygons through time (See here for how to change the timeline start/end time). Additionally, you don't need to use timers to set the positions, the time is built in to the SampledPositionProperty (although you can still add samples asynchronously).
However, this also means that the position depends on the current time in the timeline instead of a real-time array value. And you might need to keep track of a time somewhere if you aren't adding all the samples at once.
I've also never done this using ellipses before, but the semiMinorAxis and semiMajorAxis are properties, so you might still be able to use a SampledProperty.
Of course, this doesn't really matter if there are still performance issues. Hopefully it will improve as you don't need to recreate the array from scratch each callback and, depending on how you're getting the data to update the polygons, you might be able to add multiple samples at once. This is just speculation, but it's something to consider.
EDIT
Cesium can handle quite a bit of samples added to a sampled position, for example in the above code if you add a million samples to the position it takes a few seconds to load them all, but renders the polygon at any time without any performance issues. To test this, instead of adding samples using a timer, just add them all directly to the property.
for (var i = 0; i < 1000000; i++) {
var time = new Cesium.JulianDate.addSeconds(start, i, new Cesium.JulianDate());
var position = new Cesium.Cartesian3.fromDegrees(-(i % 2), 0);
positions[0].addSample(time, position);
}
However, if you run into memory problems currently there is no way to remove samples from a position property without accessing private variables. A work around would be to periodically create a new array containing new position properties and use the previous position property array's setValue() method to clear previous values or perhaps to use a TimeIntervalCollectionProperty as in this answer and remove time intervals with the removeInterval method.

Cocos2d-x turn based RPG game: run characters' attack animation in sequence

I am building a turn-based RPG game with Cocos2d-x 3.3final. I have four sprites, say sprite1, sprite2, sprite3 and sprite4. Each has an associated attack animation(class type Animate*), say sprite1attack, sprite2attack, sprite3attack, sprite4attack.
During the battle, every turn the attack order of these characters changes according to user's operation. In my code, I would like to have a menu callback function that could run the four character's attack animation in sequence when the user clicks its associated button:
void onStart(){
}
If I coded it like:
void onStart(){
sprite1->runAction(sprite1attack);
sprite2->runAction(sprite2attack);
sprite3->runAction(sprite3attack);
sprite4->runAction(sprite4attack);
}
The four animations would run all together.
Are there any good design pattern that can run the sprites' animation in any user wanted sequence?
It's OK to add variables, like vector<int> attackOrder.
When you want to put Some Actions ( from TargetedAction) in sequence, you will need to use TargetedAction.
For example in your case you need something like this:
auto sequnecedAction = Sequence::create(
TargetedAction::create(sprite1,sprite1attackAnimation),
TargetedAction::create(sprite2,sprite2attackAnimation), nullptr);
sprite1->runAction(sequnecedAction);

Square bracket notation to dynamically load library items?

So I've spent an embarrassing number of hours trying to save myself a few minutes and make my code a bit neater, and Google has produced nothing, so now I come crawling to stackoverflow. The problem is with square bracket notation + library items:
So let's say you have a MovieClip called "myMC_5", and you want to set its X position to 0..
myMC_5.x = 0;
..and if you don't want to hard-code the name of the MC but instead you want one line of code to move a specific MovieClip based on a variable, you could do something like this:
var selectMC = 5;
root["myMC_"+selectMC]x = 0;
..and this will have the exact same effect as myMC_5.x = 0, except that this time you must specify the location ("root" or "this" or something).
THE PROBLEM:
I'm working on a game in which the graphic for the background is loaded from the library, and it's different for each level. The initial loading of the vector from the library looks like this:
private var land:vector_land0 = new vector_land0();
..and this works fine, but it only loads that one specific vector. There should be about 30 or more. I'd like to just have 1 line of code in the constructor to load any of them, based on a variable which keeps track of the current level, like this:
private var land:["vector_land"+theLevel] = new ["vector_land"+theLevel]();
..but that doesn't work. I get syntax errors ("expecting identifier before leftbracket") because you need to specify the location of the object, like in the first example:
root["myMC_"+"whatever"].x = 0;
..but this library item has no "location". So, how the heck do I dynamically load a vector from the library? It's not "on the root", or anywhere else. It has no location. I refuse to believe that the standard method for accomplishing this is to create 30 different classes or write a giant block of code with 30 "if" statements, but searching Google has found nothing. :(
It sounds like you're looking for getDefinitionByName(), which you could use to do something like this:
import flash.utils.getDefinitionByName;
private var LevelVectorClass:Class = getDefinitionByName("vector_land" + theLevel) as Class;
private var land:Object = new LevelVectorClass();
This is a horrible way to solve the situation, I don't recommend using square brackets anywhere but arrays. I recommend you putting the "lands" into a LandContainer MovieClip, each frame of that MovieClip would container 1 graphic. It is much cleaner, and you could create constants to store the "identity" of the frames.Example:
var land:LandContainer = new LandContainer();
land.gotoAndStop(FIRST_LEVEL); //FIRST_LEVEL is a constant integer
You can even reuse this LandContainer instance because you can set it's visibility, remove from the display list, set it's frame to the next level without creating another instance. On second thought, I would write a wrapper for this class. Aka link it to your own class which extends the MovieClip class and create custom functions, fields... etc..
This dynamic thing is horrible, hard to maintain, and not efficient at all. Don't know why did not they delete it from AS3... they should have.

AS3. How to change character's template in adobe flash cs5 using AS3?

I'm creating flash game. Here will be abillity to choose one of two (or more) character's. So I have in library created symbol hero. It have 7 animations on click (moving, jumping, attacking etc..)
So I want to create something like hero 2, that player could choose which one likes more. Just how to do that? Create new layer in hero and add animations or how?
I'm asking that because in Action Script 3 I'm adding hero in this case and It always will add the same:
private function create_hero()
{
addChild(Hero);
Hero.gotoAndStop("stay");
Hero.x = stage.stageWidth/2;;
Hero.y = ground.y - 60;
Hero.x_speed = 0;
Hero.y_speed = 0;
}
Maybe here is abillity to make something like that layer2.addChild(Hero);?
Or I need to create new symbol hero2? I don't like this idea, because I have long code to control hero, so for every character I'll need to dublicate code. Could you help me? Thank you.
The proper way is to dynamically create an instance Hero at game start based on the game player's selection. You indeed create two (or more) symbols in Flash CS, with common frame labeling (you can use different animation lengths for different heroes), then, once you've got your hero selection (hero1,hero2,hero3 etc, regardless of their amount) you get the class name from selection and get your Hero variable to be assigned an instance of the respective class. An example:
static var heroes:Array=[hero1,hero2,hero3]; // note: symbol names!
var Hero:MovieClip; // note, not "hero1" or anything, but general MovieClip type
public function selectHero(what:int):void {
// this is called with correct "what", design yourself. I use array index
var whatHero:Class = heroes[what]; // get selected hero symbol
if (Hero && Hero.parent) Hero.parent.removeChild(Hero);
// clean up previous hero. Drop listeners here, if any
Hero = new whatHero(); // get new hero
// process as usual, don't forget to "addChild(Hero)" somewhere
}
How this works: First, you give the player a hero selection dialogue, and call selectHero with proper value of what (0 for hero1, 1 for hero2, etc, as you make your heroes array). Then, the whatHero variable is assigned the corresponding class (yes, one can assign classes to variables in AS3!) And then the class gets instantiated via new construction, and the resultant movie clip is then assigned to Hero variable. After this is done, you can use your hero as before.

retrieving a variable value from lower level

well i created some variables in the main stage level, with something like this:
for(i=0,i<10,i++){
var var_name="var_num_"+i;
this[var_name]="some value";
}//<-----------------------------------------------------works
so i get 10 variables named "var_num0", "var_num1", "var_num2" each one with some value.
and i can acces them any where calling this
var second_var=MovieClip(root).var_num0;//<--------------works
my problem comes when i want to call all the variables from a lower level or in another frame or somewhere else using another loop:
var third_var;
for(j=0,j<3,j++){
third_var=this["MovieClip(root).var_num_"+j];//<---------DOSNT WORK
trace(this["MovieClip(root).var_num_"+j]);//<------------returns "undefined"
}
how can i make this work? i tried a lot of things and nothing...
thanks you all
In your case both "root" and "this" are the scope you want to access the vars from. so try this:
var third_var:MovieClip;
for(j = 0; j < 3; j++)
{
third_var = MovieClip(root)[var_num_ + j];
trace(third_var);
}
Also you should have semi-colons in your for loop rather than comers.
I'd like to preface my answer with a suggestion you use a 'Document Class' with AS3 to make things like namespaces and inheritance much clearer. You know exactly where things are accessible when using document based, object oriented programming versus the timeline programming available through the Flash IDE (its only there because of AS1/2). Tut: http://www.kirupa.com/forum/showthread.php?223798-ActionScript-3-Tip-of-the-Day/page14
On to the answer: You are trying to move two levels of inheritance in one set of [] Another way of writing your first "Doesn't work" line is:
this.myMovieClip["var_num"+j"];
You could also use: this["MovieClip"]["var_num"+j];
Basically, you need to take the "MovieClip(root)" out of the string you are using to call your variable because you are passing through two levels of inheritance: this->MovieClip->targetVar
You need to use two periods, a period and a set square bracket or two sets square brackets to move two levels of inheritance. A period . and a set of square brackets [] both accomplish the task of moving one level deeper, so putting the . inside the string used to call up your variable won't work.
Explanation:
The following three examples all return the same variable:
myMovieClip.my_variable
myMovieClip["my_variable"]
var str:String = "my_variable";
myMovieClip[str];