I created a visual grid of sprites which are stored in an Array1.
Some of those sprites got an image placed on it.
Now I would like to drag another image on an empty grid-element.
Special case:
Several images are dragged at the same time for being placed.
Therefore a drag-container holds also an Array2 of those dragged images.
As soon as the mouse goes up, the images of Array2 should be placed on empty grid elements of Array1.
My question: How do I check if a sprite of Array1 is occupied or not?
While several images have been dragged, every image should be placed one grid-element below the previous(y-axis down). In this process it could happen that you place an image on an empty grid-element, but because several are placed below each other the next grid-element could be occupied and therefore the currently placed image should be placed to the next free grid-element.
Let's make a boolean array (let's cal it boolarr), containing true on i-th place if i-th Sprite of a grid already has an image. otherwise boolarr[i] is false. You should store boolarr in grid class, and change it each time images are added.
So, here's possible solution. We drop several images on i-th place. Let's find n next free spries
function getFreeSprites(n: int, i: position) {
var result = [];
while (result.length < n) {
if (!boolarr[i]) result.push(i);
i++;
}
return result;
}
array returned by the function will contain indexes of next n free sprites, after that you can attach images to them.
Hope that helps!
Related
I'm using libgdx and recreating pac-man, I'm currently using this code to spawn in the pellets for the level (essentially they spawn everywhere that the walls and Pac-Man aren't)
for(int x = 1; x < 27; x++) {
normalPellet.setX((x * 70) + 25);
normalPellet.setY((y * 70) + 25);
if(!(normalPellet.overlaps(walls)) {
batch.draw(pellet,normalPellet.x,normalPellet.y);
pelletCount++;
}
}
My problem is that I don't know how to make it so that when Pac-Man moves over the pellets they get "eaten" and are removed from the field. When Pac-Man moves over them, they do disappear, but as soon as Pac-Man moves to a different place on the map they immediately reappear. How do I make it so they go away permanently?
Typically a game is redrawn on each render call (the render loop). Your game runs by calling your root render() method repeatedly. At the beginning of your render method, you clear the screen, and then draw everything again. So to remove something, you simply stop drawing it.
You need to create a List of all active pellets. This can be a list of some Pellet class that you create that has coordinates and any other state data that is relevant to your game (such as whether it's a "super-pellet"). Or it could just be a list of Vector2s if all your pellets are identical so the only thing you need to track is their position.
When a round starts, you should create all the pellets you need at the coordinates they should be at and add them all to the List.
Then, instead of doing your for(int x = 1; x < 27; x++) loop to draw them, you should loop through your list instead and draw each pellet based on its position (and possibly other data, for example if there are super pellets, you could choose how big to draw it based on that data).
When the character moves, you can check its overlap with each pellet in the list. When a pellet is overlapped, you can remove it from the list and update your score. When it is removed from the list, it will no longer be drawn in the other part of your code where you loop through the list to draw them.
I am writing now a flash game and I run into a an issue. I have a map for the game which is defined as a 2-D array, where each element represents a component of the map. The player is always in the center of the map.
The problem is when the player reaches one end of the map. Now it is empty space. I want that the player instead of seeing the empty space, to see another end of the map and in this way, the map will loo like it goes around.
So for example if the player goes to right he will eventually start seeing the the left side of the map and the world will look continuous.
Does anyone knows how to implement this functionality?
You could make the array 2 times and put the first one behind the second one again and than the second one behind the first etc etc..
It's done here with 2 pictures, just use the arrays instead:
//The speed of the scroll movement.
var scrollSpeed:uint = 2;
//This adds two instances of the movie clip onto the stage.
var s1:ScrollBg = new ScrollBg();
var s2:ScrollBg = new ScrollBg();
addChild(s1);
addChild(s2);
//This positions the second movieclip next to the first one.
s1.x = 0;
s2.x = s1.width;
//Adds an event listener to the stage.
stage.addEventListener(Event.ENTER_FRAME, moveScroll);
//This function moves both the images to left. If the first and second
//images goes pass the left stage boundary then it gets moved to
//the other side of the stage.
function moveScroll(e:Event):void{
s1.x -= scrollSpeed;
s2.x -= scrollSpeed;
if(s1.x < -s1.width){
s1.x = s1.width;
}else if(s2.x < -s2.width){
s2.x = s2.width;
}
}
You simply check if your player is about to get off the "right" or "left" edge of the map, and position him at the other edge. To draw a circular map, you can use the following technique: if you are about to draw a column of a number that exceeds the map's width, decrease that number by width and draw the column at resultant index; and if you are about to draw a column at index below zero, add width and draw the column at resultant index. If you are in troubles of making a hitcheck at continuous map's borders, you can employ the same trick to find neighbors. (The "circular array" is a pretty basic algorithmic problem, and is resolved in many ways already)
You have a few options here. You can do the pac-man style of just making your character pop up on the other side of the screen, but that would require you to abandon the cool bit of the character being in the middle at all times.
On to the real suggestions:
If you're not implementing your array as one solid object (i.e. making it draw individual collumns/rows at a time) then this is a no-brainer. Just have a function that returns the index of the next collumn/row, within certain bounds. Like, if your array is 40 elements wide, when it tries to draw element 41, subtract the size of the array, and make it draw element 1 instead.
If your array is one solid object (like if you drew it onto a stage object and are just manipulating that) and it's not very big, you could probably get away with drawing a total of four of them, and just having a new one cover up any whitespace that's about to appear. Like, as you approach the right edge of the first array, the second array moves to the right of it for a lawless transition.
If your array is a solid object and is very big, perhaps you could make eight buffer objects (one per edge and one per corner) that hold approximately half a screen's worth of the array. That way as you approach the right edge, you see the left edge, but then when you cross into the buffer zone, you could teleport the player to the corresponding position on the left of the array, which has the buffer for the right size. To the player, nothing has changed, but now they're on the other side of the world.
I am developing a 2D games with cocos2dx, in which I am still very new... inside the game, there's a number of UI Elements that I'd like to group together as one (I intend to group them into CCLayers). For example a few text labels and sprites form a CStatBar which is a CCLayer. This CStatBar will then be included in the various other CCLayer
How do I do that? I created the CStatBar class and then, inside the containing class's init() function, I CStatBar::create() and call this->addChild(pStatBar) however, the statbar did not appear... is there any obvious thing that I missed? All the positions are correct. Thanks!
EDIT:
Notes:
1. ccTouchesBegan of the sublayer is called, however it is not rendered/seen
2. How do I resize the sublayer so that it only cover partial area of the parent layer? Supposedly the CStatBar should only cover 10% of the top area of the screen, not the whole screen...
inside the CParent::init() function, you can initialize the CSublayer like so:
// Create and initialize CSublayer
CSublayer* pSublayer= CSublayer::create();
float fWidth = pSublayer->getContentSize().width;
float fHeight = pSublayer->getContentSize().height;
pSublayer->setPosition(ccp(fWidth/2.0f, fHeight/2.0f));
this->addChild( pSublayer );
and your CSublayer can be defined like other CCLayer.
If you want to restrict the CSublayer to be smaller than the CParent layer, you can do so inside its init function like so:
CSublayer::init() {
// initialize the size with the size of the background sprite
CCSprite *pSpriteBackground = CCSprite::createWithSpriteFrame(
CCSpriteFrameCache::sharedSpriteFrameCache()->spriteFrameByName("background.png")
);
this->setContentSize(CCSize(pSpriteBackground->getContentSize().width, pSpriteBackground->getContentSize().height));
pSpriteBackground->setPosition(ccp(fScreenHalfWidth, fScreenHeight-(pSpriteBackground->getContentSize().height/2.0f)));
this->addChild(pSpriteBackground);
}
When we click on an image it should come in front as the selected image, but I dont want to change the index value of that image
canvas1.setChilIndex(Image(event.target), numChildern-1)
The above line is changing the index value of the selected image and setting it to maximum-1 (for ex: 5-1 = 4 as index value). I Need alternate for above line that keeps the same index for the image.
Any help is appreciated.
What you can do, is in your click handler store the index of the item clicked, then on the next click (or whenever you want), send the item back to its previous index:
var previousImg:Image;
var previousIndex:int;
function selectImage(img:Image):void {
deselectImage(); //if there is already a selected image, put it back before moving this new one to the top
previousImg = img;
previousIndex = canvas1.getChildIndex(img);
canvas1.addChild(img); //brings it to the front
}
function deselectImage():void {
if(previousImg){
canvas1.setChildIndex(previousImage, previousIndex);
previousImg = null; //null the var in case you call this method manually
}
}
so in your click handler, do this instead of the line you have in your question:
selectImage(Image(event.target));
With this method, anytime you call selectImage, it will put the last click one back where it belongs. You could also call deselectImage manually if you so desired.
It is impossible, because in flash child index is the only criterion of drawing order.
If you want to hold the order of adding images, you can store images, for example, in array, then every next item will have index in order of adding.
When I see your question, I have the same ideas that LondonDrugs and Roman suggested above. However, your question is quite simple, so the answer is not possible.
The situation is quite complicated if I don't know the flow of the application.
For example, if you will add image to your canvas at the run time after you selected an image then which order of index you would like to roll back?
My suggestion:
You can set a cut point that you want to keep the order of index, then use a loop to find the index of all the image and keep it in an array. When the user finished playing, roll the index back to the cut point.
I'm trying to position an image on top of another image based upon the make-up of the smaller image. The smaller image is a cut-out of a larger image and I need it to be positioned exactly on the larger image to make it look like a single image, but allow for separate filters and alphas to be applied. As the images are not simple rectangles or circles, but complex satellite images, I cannot simply redraw them in code. I have quite a few images and therefore do not feel like manually finding the position of each image every and hard setting them manually in actionscript. Is there any way for me to sample a small 5-10 sq. pixel area against the larger image and set the x and y values of the smaller image if a perfect match is found? All the images are in an array and iterating through them has already been set, I just need a way to sample and match pixels. My first guess was to loop the images pixel by pixel right and down, covering the whole bitmap and moving to the next child in the array once a match was found, leaving the matched child where it was when the perfect match was found.
I hope I understood your question correctly.
There may be an option that uses copypixels to achieve what you want. You can use the bitmapdata.rect value to determine the size of the sample you want, and loop through the bigger bitmap using thet rectangle and a moving point. Let's see if I can code this out...
function findBitmapInBitmap(tinyimg:BitmapData, largeimg:BitmapData):Point {
var rect:Rectangle = tinyimg.rect;
var xbound:uint = largeimg.rect.width;
var ybound:uint = largeimg.rect.height;
var imgtest:BitmapData = new BitmapData(tinyimg.rect.width, tinyimg.rect.height);
for (var ypos:uint = 0, y <= ybound, y++) {
for (var xpos:uint = 0, x <= xbound, x++) {
imgtest.copyPixels(largeimg, rect, new Point(xpos, ypos);
if (imgtest.compare(tinyimg) == 0) return new Point(xpos, ypos);
}
}
return new Point(-1,-1); // Dummy value, indicating no match.
}
Something along those lines should work - I'm sure there's room for code elegance and possible optimization. However, it seems like something like this method would be very slow, since you'd have to check each pixel for a match.
There is a better way. Split your big image into layers, and use the blitting technique to composite them at runtime. In your case, you could create a ground texture without satellites, and then create the satellites separately, and use the copyPixels method to place them whereever you want. Google "blitting in as3" to find some good tutorials. I'm currently working on a game project that uses this technique and it's a very good method.
Good luck!
Edit: Forgot to code in a default return statement. Using this method, you'd have to return an invalid point (like (-1,-1)) and check for it outside the function. Alternatively, you could just copy your small bitmap to the big one within the function, which would be much more logical, but I don't know your requirements.
You need to find pixel sequence in the big image. BitmapData.getPixel gives you pixel value. So get first pixel from small image, find it in big image, then continue comparing until you find full match. If you have trouble to code that, feel free to ask.
For the actual comparison, there's BitmapData.compare which returns the number 0 if the BitmapData objects are equivalent.