I am making game in libgdx. I want to show tutorials on game start and disappear after few seconds.My code is given below
public class HeroCar{
static final int TUTE_STATE_SHOW = 0;
static final int TUTE_STATE_HIDE = 1;
int tuteState;
float tuteStateTime = 0;
public HeroCar()
{
tuteState = TUTE_STATE_SHOW;
}
public void update(float deltaTime){
if(tuteStateTime >= 0.56f){
tuteStateTime = 0;
tuteState = TUTE_STATE_HIDE;
}
else{
tuteState = TUTE_STATE_SHOW;
}
tuteStateTime += deltaTime;
}
and in game play screen class render method my code is
if(world.heroCar.tuteState == HeroCar.TUTE_STATE_SHOW){
spriteBatch.draw(Assets.speedingup_region, 480 / 2 - 172 / 2, 400, 172, 30);
}
}
Or can can just use Car distance
if(herocar.position.x<50&&canShowTute)
{
fon.draw(batcher,string,posx,posy);
}
else if(herocar.position.x>50&&canShowTute)
{
canShowTute=false;
}
This way u dont have to manage a variable for statetime
Also if car crosses a ceratain distance than manage that no further need to show tute next time.
if(tuteStateTime >= 0.56f){
tuteStateTime = 0; //--------------wrong
tuteState = TUTE_STATE_HIDE;
}
donot set
tuteStateTime = 0
because if you set it 0 then in the next cycle it will check time > 0.56f , then it goes to else block and set state = show...... Hence your tutorial will never dissappear. it will always remain in show state.
If you are saying about alpha of texture then may be this could help.
make
Sprite sprite = new Sprite(Assets.speeding_upregion);
in constuctor. and in render cyle
float step = 0;
float speed = 5;
float alpha = 0;
step = alpha > .9f ? -speed : alpha < .1f ? speed : step; alpha += step * deltaTime;
sprite.draw(spritebatch, alpha);
add your condition before draw if you want to draw or not.
Related
This is for homework, I have most of this done but I am stuck on the final step (implementing a mouse event that will change one of my randomized colored squares to become red instead of it's assigned colors) and am concerned that using the methods provided by my prof are not suitable to this, as he has us repaint after mouse event (which I feel my code will just override with more random colors). Any assistance or nudge in the right direction would be helpful, and I am sure this is a mess.
Update as per Camickr's assistance, my code has changed to the following:
import java.awt.GridLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.util.Random;
import javax.swing.*;
// MouseListener Imports
import java.awt.event.MouseListener;
import java.awt.event.MouseEvent;
public class Test extends JPanel implements MouseListener
{
static Color[][] framework = new Color[8][8];
static int redCounter = 0;
// main Creates a JFrame and instantiates the 2d array of color objects
public static void main(String[] args)
{
// The frame handles all the outside window work
JFrame frame = new JFrame("MouseListener demo");
// Allows the 'X' in the upper right to cause the program to exit
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//Create and set up the content pane.
// contentPane holds a panel
JComponent newContentPane = new Test();
// MouseListenerDemo isa JPanel isa JComponent
newContentPane.setOpaque(true); //content panes must be opaque
frame.setContentPane(newContentPane);
//Display the window.
frame.pack();
/* Causes this Window to be sized to fit the preferred size and layouts of its subcomponents.
The resulting width and height of the window are automatically enlarged if either of dimensions
is less than the minimum size as specified by the previous call to the setMinimumSize method.
If the window and/or its owner are not displayable yet, both of them are made displayable before
calculating the preferred size. The Window is validated after its size is being calculated.
*/
frame.setVisible(true);
for (int x = 0; x < framework.length; x++) {
for (int y = 0; y < framework.length; y++) {
Color rc = randomColor();
framework[x][y] = rc;
}
}
}
// Constructor
public Test()
{
// layout the panel with an area in which to draw
super(new GridLayout(0,1));
// get Graphics object, which allows you to draw on the panel
// set initial size of the panel
setPreferredSize(new Dimension(400, 500));
// ADD this JPanel to the list of components notified when a mouse event happens
this.addMouseListener(this);
// calls paint()
repaint();
}
// draws the screen
public void paint(Graphics g)
{
// Get the size
Dimension d = this.getSize();
int size = 50; // The edge length of the squares
int xSt = 50; // Starting x-coordinate
int ySt = 50; // Starting y-coordinate
int n = 8; // n X n board
int xPos, yPos;
for(int row = 0; row < framework.length; row ++){
for (int col = 0; col < framework.length; col ++){
xPos = xSt*col;
yPos = xSt*row;
// set color
g.setColor (framework[row][col]);
// Draw square
g.fillRect(xPos, yPos, size, size);
}
}
g.setColor(Color.black);
g.drawString("There are " + redCounter + " reds." , d.width/3, d.height);
}
public static Color randomColor(){
Random rg = new Random();
int result = rg.nextInt(12);
Color color;
switch(result){
case 0: color = Color.black;
break;
case 1: color = Color.blue;
break;
case 2: color = Color.cyan;
break;
case 3: color = Color.darkGray;
break;
case 4: color = Color.yellow;
break;
case 5: color = Color.green;
break;
case 6: color = Color.lightGray;
break;
case 7: color = Color.magenta;
break;
case 8: color = Color.orange;
break;
case 9: color = Color.pink;
break;
case 10: color = Color.red; redCounter = redCounter + 1;
break;
case 11: color = Color.white;
break;
default: color = Color.black;
break;
}
return color;
}
// MouseListener methods
public void mousePressed(MouseEvent evt)
{
// demonstrates how to use the parameter
// to get the position of the mouse press
Dimension d = this.getSize();
int x = evt.getX();
int y = evt.getY();
System.out.println(x+","+y);//these co-ords are relative to the component
System.out.println(evt.getSource());
for (int i = 0; i < framework.length; i++) {
for (int j = 0; j < framework.length; j++) {
System.out.println(framework[i][j]);
if (evt.getSource().equals(framework[i][j])) {
framework[i][j] = Color.red;
redCounter = redCounter + 1;
}
}
}
repaint(); // redisplay the frame by eventually calling the paint() method
}
// do nothing for the other mouse actions
public void mouseReleased(MouseEvent evt) {}
public void mouseClicked(MouseEvent evt) {}
public void mouseEntered(MouseEvent evt) {}
public void mouseExited(MouseEvent evt) {}
}
am concerned that using the methods provided by my prof are not suitable to this, as he has us repaint after mouse event (which I feel my code will just override with more random colors).
The repaint() in the MouseEvent is correct. However more random colors will be generated because your painting code is incorrect.
A painting method should only paint the state of your component, not change the state. Therefore:
You need to keep a data structure (lets say a 2D array) to hold the Color of each cell. In the constructor of your class you would then iterate through this array and assign the random colors to each entry in the array.
Then in the painting method you just iterate through the array and paint each cell using the color from the array.
Note you should be overriding paintComponent(), not paint() for the custom painting.
Then in your MouseListener code you just reset the Color in the Array for the cell that was clicked and invoke repaint().
I fixed it by getting the position of x/y and dividing them by 50 (my square height/width) and putting the int into the array index.
public void mousePressed(MouseEvent evt)
{
// demonstrates how to use the parameter
// to get the position of the mouse press
Dimension d = this.getSize();
int x = evt.getX()/50;
int y = evt.getY()/50;
framework[y][x] = Color.red;
redCounter = redCounter+1;
repaint(); // redisplay the frame by eventually calling the paint() method
}
I'm currently stuck with my approach below. I'm not entirely sure if using "hitTestObject" method is appropriate in pairing the pieces to their respective place. I was able to at least match the chess piece to their respective location (that's the best I can do and I feel i'm doing it wrong) but I'm now stuck in counting how many pieces are actually in their correct places. e.g. when I move the pawn to a different tile, it will still count as one, I also want to avoid duplicate counting, example, If pawn is already in the correct location, it will just count as 1, and if it was moved, then that count will be removed. Only count the pieces that are in the correct tile.
My goal here is to be able to make all the chess pieces draggable and determine if they're in their respective location. If ALL the chess pieces are in their location, it will trace or call a function.
Thank you!
import flash.events.Event;
import flash.display.MovieClip;
import flash.events.MouseEvent;
/* Declaring an X and Y variable to be used as a reset container */
var xPos: int, yPos: int;
/* Attaching event listeners for each chess piece */
addListeners(
king, queen, bishop_1, bishop_2, knight_1, knight_2, rook_1, rook_2,
pawn_1, pawn_2, pawn_3, pawn_4, pawn_5, pawn_6, pawn_7, pawn_8);
/* Getting the original x and y postion to be used as a reset */
function getPosition(currentTarget: Object): void {
xPos = currentTarget.x;
yPos = currentTarget.y;
}
/* Function to get the suffix value of an object. example, I need to get the value 4 from "pawn_4" */
function getLastCharInString($s: String, $pos: Number): String {
return $s.substr($s.length - $pos, $s.length);
}
/* A simple function that rotates the chess piece */
function lift(object: Object, rot: Number) {
object.rotation = rot;
}
function dragObject(e: MouseEvent): void {
getPosition(e.currentTarget);
lift(e.currentTarget, -10);
getChildByName(e.currentTarget.name + "_hs").alpha = 1;
e.currentTarget.startDrag();
}
/* This variable is supposed to hold the value of each piece that is correctly placed in each tile.
The total score should be 16 as there are 16 pieces. Only correcly placed piece should be added in the total score. */
var counter:int;
function stopDragObject(e: MouseEvent): void {
var curretTarget = e.currentTarget.name;
lift(e.currentTarget, 0);
/* Hide active hotspots */
getChildByName(e.currentTarget.name + "_hs").alpha = 0;
var multiplePieceSufix = Number(getLastCharInString(curretTarget, 1));
if (multiplePieceSufix >= 1) {
/* Boolean variables that checks whether the current piece is active*/
var isPawn: Boolean = false,
isBishop: Boolean = false,
isKnight: Boolean = false,
isRook: Boolean = false,
currentTargeName;
var widthDiff = getChildByName(e.currentTarget.name + "_hs").width - getChildByName(e.currentTarget.name).width / 2;
var heightDiff = getChildByName(e.currentTarget.name + "_hs").height - getChildByName(e.currentTarget.name).height / 2;
if (curretTarget.substr(0, 4) == "pawn") {
isPawn = true;
} else if (curretTarget.substr(0, 6) == "bishop") {
isBishop = true;
} else if (curretTarget.substr(0, 6) == "knight") {
isKnight = true;
} else if (curretTarget.substr(0, 4) == "rook") {
isRook = true;
}
if (isPawn == true) {
/* there are total of 8 pieces of pawn */
for (var w = 1; w < 9; w++) {
currentTargeName = this["pawn_" + w + "_hs"];
if (e.target.hitTestObject(currentTargeName)) {
/* For some reason the chess pieces are not aligning with their "_hs" version, I already checked their registry point and it seem to be normal.
so to fix, I had to manually add some hard coded values to adjust their location. */
e.currentTarget.x = currentTargeName.x - 8;
e.currentTarget.y = currentTargeName.y + currentTargeName.height;
}
}
} else if (isBishop == true) {
for (var x = 1; x < 3; x++) {
currentTargeName = this["bishop_" + x + "_hs"];
if (e.target.hitTestObject(currentTargeName)) {
e.currentTarget.x = currentTargeName.x - 9;
e.currentTarget.y = currentTargeName.y + currentTargeName.height - 18;
}
}
} else if (isKnight == true) {
for (var y = 1; y < 3; y++) {
currentTargeName = this["knight_" + y + "_hs"];
if (e.target.hitTestObject(currentTargeName)) {
e.currentTarget.x = currentTargeName.x - 8;
e.currentTarget.y = currentTargeName.y + currentTargeName.height;
}
}
} else if (isRook == true) {
for (var z = 1; z < 3; z++) {
currentTargeName = this["rook_" + z + "_hs"];
if (e.target.hitTestObject(currentTargeName)) {
e.currentTarget.x = currentTargeName.x - 8;
e.currentTarget.y = currentTargeName.y + 62;
}
}
}
} else {
if (e.target.hitTestObject(getChildByName(e.currentTarget.name + "_hs"))) {
/* Again, I'm not sure why the pieces are not aligning as intended.
modX and modY is a holder for the adjustment value. I'm not comfortable
seeing this approach myself, but I also run out of ideas how to fix it. */
var modX: Number, modY: Number;
if (e.currentTarget.name == "king") {
modX = 11;
modY = 53;
} else {
modX = 11;
modY = 29;
}
e.currentTarget.x = getChildByName(e.currentTarget.name + "_hs").x - modX;
e.currentTarget.y = getChildByName(e.currentTarget.name + "_hs").y + getChildByName(e.currentTarget.name + "_hs").height - modY;
}
}
/* This is supposed to add to the total score or count of how many pieces are placed correctly.
Thie problem with thi scounter, as it also counts any piece that is places to any "_hs" */
counter++;
trace(counter);
e.currentTarget.stopDrag();
}
function addListeners(...objects): void {
for (var i: int = 0; i < objects.length; i++) {
objects[i].addEventListener(MouseEvent.MOUSE_DOWN, dragObject);
objects[i].addEventListener(MouseEvent.MOUSE_UP, stopDragObject);
// hide hotspots
getChildByName( objects[i].name + "_hs" ).alpha = 0;
}
}
Source: Download the FLA here
--
Updates:
I have added comments in my code to clarify what I'm trying to accomplish.
I'm planning to do board game in flash which has similar function and behaviour to this. User can drag the object to a specified tile and check wether that object belongs there or not.
After reviewing your code, your question is quite broad. I'm going pair it down to what seems to be your main concern - the score / counting correctly moved pieces.
Right now, you do the following every time an object is dragged:
counter++;
This means that the counter will increment no matter where you drag the object, and no matter how times you drag the object. (so even if the piece was already in the correct spot, if you dragged it a second time it will still increment your counter).
What you need to do, is associate a flag with each object to indicate whether it is in the correct location or not, and set that flag to the appropriate value every time that object is done dragging.
Something like this:
//don't use target, use currentTarget
if (e.currentTarget.hitTestObject(currentTargeName)) {
e.currentTarget.correct = true; //since MovieClips are dynamic, you can just make up a property on them and assign a value to it.
//to fix your alignment:
e.currentTarget.x = currentTargeName.x + ((currentTargetName.width - e.currentTarget.width) * 0.5);
e.currentTarget.y = currentTargeName.y + currentTargeName.height;
}else{
//if the hit test is false, mark it as NOT correct
e.currentTarget.correct = false;
}
Then, later to know the current count, iterate over all the pieces and check their correct value. This would be much easier if all your pieces were in an array.
var allPieces:Array = [king, queen, bishop_1, bishop_2, knight_1, knight_2, rook_1, rook_2,
pawn_1, pawn_2, pawn_3, pawn_4, pawn_5, pawn_6, pawn_7, pawn_8];
function countCorrect():Boolean {
var ctr:int = 0;
for(var i:int=0;i<allPieces.length;i++){
if(allPieces[i].correct) ctr++;
}
return ctr;
}
trace(countCorrect() + " of " allPieces.length " are correct");
As an aside, this best way to do this would be with some custom class files. That would however require a complete refactoring of your code.
Also, you probably don't want to use hitTestObject, as even if a piece is mostly over a neighbor, it will still be true as long as 1 pixel of it's bound touch 1 pixel of the tile. Better would be to do a hitTestPoint on the tile, and pass in the center point of the piece (the the middle of the piece has to be touching the tile for it to count).
//a point that is the center of the events current target (the piece)
var point:Point = new Point();
point.x = e.currentTarget.x + (e.currentTarget.width * 0.5);
point.y = e.currentTarget.y - (e.currentTarget.height * 0.5);
if (currentTargetName.hitTestPoint(point)) {
I want to change the size of a Sprite which is animating. How can I do this ? I tried to change its size by using setScale property but it is not working here. where I am doing wrong ?
CCArray* frames = CCArray::createWithCapacity(3);
CCSpriteFrameCache* frameCache = CCSpriteFrameCache::sharedSpriteFrameCache();
char file[100] = {0};
for (int i = 0; i < 3; i++)
{
sprintf(file, "bird%d.png", i);
CCSpriteFrame* frame = frameCache->spriteFrameByName(file);
frames->addObject(frame);
}
CCAnimation* animation = CCAnimation::createWithSpriteFrames(frames, 0.1);
CCAnimate* animate = CCAnimate::create(animation);
CCRepeatForever* repeat = CCRepeatForever::create(animate);
bird->runAction(repeat);
bird->setScale(0.7);
Try like this. It's working fine.
CCSprite* pSprite = CCSprite::create("pic2.png");
pSprite->setPosition( ccp(size.width/2, size.height/2) );
this->addChild(pSprite, 0);
//Animation
CCAnimation *animate = CCAnimation::create();
for (int i = 1; i <=3; i++)
{
char frameName[128] = {0};
sprintf(frameName, "pic%d.png", i);
animate->addSpriteFrameWithFileName(frameName) ;
}
animate->setDelayPerUnit(0.1f); // This animation contains 3 frames, will continuous 2.8 seconds.
animate->setRestoreOriginalFrame(true); // Return to the 1st frame after the 3rd frame is played.
CCAnimate *animaction = CCAnimate::create(animate);
CCRepeatForever *reptaction = CCRepeatForever::create(animaction);
pSprite->runAction(reptaction);
pSprite->setScale(0.3);
The supplied DisplayObject must be a child of the caller.
What a basic error right? Iv fixed many of these but maybe im just over thinking this... idk anyways...
I have a game drawing a map based off a perlin noise and a bitmap, well drawing the WHOLE map and moving EVERY tile of the map is unpractical and not smart. So iv set it to draw a section of the map and when you push the arrow keys it deletes the tiles and re draws them with the new array of tiles it needs. BUT
When i move from the first set of the map, to the next set it deletes the tiles and re draws them fine, but when i try to move to another section of the map it gives me supplied display object must be a child of the caller. Which i get the error, it says what its deleting has to be within what its deleting from (i think). But im not sure why it works the first time but not the next? My guess is it has something to do with the worldTiles sprite that im adding the tiles too. But i dont know how to go about fixing it
If you set the map width to 1600, then push the right key once, it will draw the next area tiles, but you cant go anywhere else without getting an error
http://www.fastswf.com/xl3LXbg
On the level class, which is a class that runs when it reaches a certain frame on the timeline. Aka a class connected to a MovieClip on the screen. Within that class I create a new World.class object
world = new World(this);
This just creates the worldTiles sprite onto the level class and runs the first generate tile when the class is first ran
public function World(parentMC:MovieClip)
{
worldTiles = new Sprite();
parentMC.addChild(worldTiles);
generateTile();
}
This is what sets the X and Y of the drawRect and the X and Y of the array it draws the tiles of.
if (k.keyCode == Keyboard.RIGHT)
{
world.deleteTiles();
world.X += 800/world.TILE_SIZE;
world.generateTile();
X += 800/MAP_SCALE;
}
if (k.keyCode == Keyboard.LEFT)
{
world.deleteTiles();
world.X -= 800/world.TILE_SIZE;//the actual X width of the tiles being drawn
world.generateTile();
X -= 800/MAP_SCALE;//drawRect
}
This is what im using to delete the tiles on the screen.
public function deleteTiles()
{
if (tilesInWorld.length > 0)
{
for (var i:int = 0; i < tilesInWorld.length; i++)
{
worldTiles.removeChild(tilesInWorld[i]);
}
}
}
And then when the tiles get re add'd it re runs the generateTiles() function which is this
public function generateTile()
{
for (var i=X; i < X+80 i++) //using 80,60 cause thats the screen width / 10, which is default tile size
{
for (var j=Y+60; j < grid_height; j++)
{
hm = heightmap[i][j];
if (hm >= 0.84)
{
tile = new Water();
}
else if (hm >= 0.8 && hm < 0.84)
{
tile = new Shallow();
}
else if (hm >= 0.7 && hm < 0.8)
{
tile = new Sand();
}
else if (hm >= 0.2 && hm < 0.7)
{
tile = new Tile();
}
else
{
tile = new Stone();
}
tile.width = TILE_SIZE;
tile.height = TILE_SIZE;
worldTiles.x = 0;
worldTiles.y = 0;
tile.x = TILE_SIZE * (i % grid_width);
tile.y = TILE_SIZE * (j % grid_height);
tilesInWorld.push(tile);
worldTiles.addChild(tile);
}
}
}
You're never removing the tiles from your tilesInWorld array, so the second time you call deleteTiles it's attempting to delete tiles that were already deleted. Try something like this:
public function deleteTiles()
{
while (tilesInWorld.length > 0)
{
// this will remove the tile from the array, then remove it from the display list
worldTiles.removeChild(tilesInWorld.pop());
}
}
first of all thanks a lot for taking interest in my question. I am trying to modify a flash as3 bubble burst game and add a scoring system to it. I am pasting the code where it detects the bubbles group and bursting them.
/**
* Checks single ball for touching another ball with the same color
* #param ball
*/
private function checkHit(ball:Ball):void {
_checkingNum++;
ball.checked = true;
var point:Point;
var point2:Point;
var d:Number;
var scorenet:Number;
for (var j:int = 0; j < _tabBalls.length; j++) {
if (Ball(_tabBalls[j]).color == ball.color) {
if (!_tabBalls[j].checked && !inTab(_theSame, _tabBalls[j])) {
point = new Point(ball.x, ball.y);
point2 = new Point(Ball(_tabBalls[j]).x, Ball(_tabBalls[j]).y);
d = countD(point, point2);
if (d < _BALL_WIDTH + 4) {
_theSame.push(_tabBalls[j]);
checkHit(_tabBalls[j]);
/*score system*/
scorenet = scorenet + 10;
trace (scorenet);
}
}
}
}
_checkingNum--;
if (_checkingNum == 0) {
if (_theSame.length >= 3) {
for (var i:int = 0; i < _theSame.length; i++) {
killBall(Ball(_theSame[i]));
Ball(_theSame[i]).kill();
}
_noeffect = 0;
} else {
_noeffect++;
if (_noeffect >= _MAX_NO_EFFECT) {
_noeffect = 0;
addNewLine();
}
}
}
}
Now I added a variable called scorenet and later I am trying to add 10 to it each time a bubble bursts but thats obviously not working. the trace is returning a value of '0' each time a bubble bursts so if in total of say 4 bubbles get burst it returns a value of 0 , 0 ,0 , 0 . I was wondering if there was someway to trace the number of 0 it returns and then add 10 to it each time , it will work fine then. Any help would be highly appreciated. Thanks.
You are using local variables to make scoring. local variables are lost when a method call is complete : it cannot be used to store persistent value like score. you should use member variables or static variables, which persists regardless of method calls.
Your calculation is NaN+10, because local variable scorenet is INITIALIZED every time checkHit() is called. so trace is showing "0". You have to deal with problem 1, or it will just be "10, 10, 10, 10..."
I added this
public var scorenet:Number = 0; //as variable
and added the score system
/score system/
if(_checkingNum > 1 ) {
scorenet = scorenet + _checkingNum + 10 ;
_mainTimeline.scoreField.text = scorenet;
} else if(_checkingNum >= 4 ) {
scorenet = scorenet + _checkingNum + 20 ;
_mainTimeline.scoreField.text = scorenet;
}