I have been stuck on this for about a week, I have searched all over the internet trying to find a solution of how to create a 2d cube effect using shear, I have tried numorous equations and this is the closest I have gotten in a week, it's purely math I believe but I can't figure it out. It is for a Multiplayer game, here is a video on Youtube of what I currently have with shearing.
https://www.youtube.com/watch?v=J0qP7T0k6xk
Here is my code:
public void addWall(Graphics2D g2d, ImageIcon img, int objX, int objY, int dir) {
//objX = objX/16;
objX = objX*32;
//objY = objY/16;
objY = (objY+4)*32;
int OffsetX = screen.width;
int OffsetY = screen.height*0;
if(dir == 1) {
//g2d.drawImage(img.getImage(), (((2*objX)+OffsetX)-(player.x*2)), (((2*objY)+OffsetY)-(player.y*2)) ,32*SCALE, ((32*SCALE)*-2)-(player.y-objY), null);
} else if(dir == 0) {
g2d.drawImage(img.getImage(), (((2*objX)+OffsetX)-(player.x*2)), (((2*objY)+OffsetY-(32*SCALE))-(player.y*2)) ,32*SCALE, ((32*SCALE)*-2)-(player.y-objY), null);
}
double skewX = (((player.x-objX)*2)*.100)*.1;
double skewY = 0;
//int x = (skewX < 0) ? -skewX*(32) : 0;
AffineTransform reset = g2d.getTransform();
AffineTransform at = AffineTransform.getTranslateInstance((-skewX*100) , 0);
at.shear(skewX, skewY);
//g2d.translate((((2*objX)+OffsetX)-(player.x*2)), (((2*objY)+OffsetY)-(player.y*2)));
// g2d.scale(SCALE, (((SCALE)*-2)-(player.y-objY)));
g2d.setTransform(at);
g2d.drawImage(img.getImage(), (((2*objX)+OffsetX)-(player.x*2)), (((2*objY)+OffsetY)-(player.y*2)) ,32*SCALE, ((32*SCALE)*-2)-(player.y-objY), null);
g2d.setTransform(reset);
//g2d.dispose();
}
public void addRoof(Graphics2D g2d, ImageIcon img, int objX, int objY) {
//objX = objX/16;
objX = objX*32;
//objY = objY/16;
objY = (objY+2)*32;
int shadowY = (objY+3)*32;
int OffsetX = screen.width;
int OffsetY = screen.height*0;
/* SHADOW */
/* SHADOW */
ImageIcon shadow = new ImageIcon("./res/shadowPixel.png");
g2d.drawImage(shadow.getImage(), (2*objX+OffsetX)-(player.x*2), (2*objY+(32*SCALE)+OffsetY)-(player.y*2), 32*SCALE, 32*SCALE, null);
/* SHADOW */
/* SHADOW */
g2d.drawImage(img.getImage(), (3*objX+OffsetX)-(player.x*3), (3*objY+OffsetY)-(player.y*3), 32*SCALE, 32*SCALE, null);
}
Related
There are balls in my app that just fly through display. They draws as I want. But now I want to draw the trail behind them.
All I could make is just drawing by canvas.drawPath something like following picture:
But it is not what I want. It should have pointed tail and gradient color like this:
I have no idea how to make it. Tried BitmapShader - couldn't make something right. Help, please.
Code:
First of all, there is Point class for position on display:
class Point {
float x, y;
...
}
And trail is stored as queue of Point:
private ConcurrentLinkedQueue<Point> trail;
It doesn't matter how it fills, just know it has size limit:
trail.add(position);
if(trail.size() > TRAIL_MAX_COUNT) {
trail.remove();
}
And drawing happened in DrawTrail method:
private void DrawTrail(Canvas canvas) {
trailPath.reset();
boolean isFirst = true;
for(Point p : trail) {
if(isFirst) {
trailPath.moveTo(p.x, p.y);
isFirst = false;
} else {
trailPath.lineTo(p.x, p.y);
}
}
canvas.drawPath(trailPath, trailPaint);
}
By the way, trailPaint is just really fat paint :)
trailPaint = new Paint();
trailPaint.setStyle(Paint.Style.STROKE);
trailPaint.setColor(color);
trailPaint.setStrokeWidth(radius * 2);
trailPaint.setAlpha(150);
I see you want to see a gradient on the ball path, you could use something like this
int x1 = 0, y1 = 0, x2 = 0, y2 = 40;
Shader shader = new LinearGradient(0, 0, 0, 40, Color.WHITE, Color.BLACK, TileMode.CLAMP);
trailPaint = new Paint();
trailPaint.setShader(shader);
This is what you should change your trailPaint to and see if it works.
provided from here.
I found solution. But still think it is not the best one.
First of all there are my class fields used for that task.
static final int TRAIL_MAX_COUNT = 50; //maximum trail array size
static final int TRAIL_DRAW_POINT = 30; //number of points to split the trail for draw
private ConcurrentLinkedQueue<Point> trail;
private Paint[] trailPaints;
private float[][] trailPoss, trailTans;
private Path trailPath;
Additionally to trailPath object I used PathMeasure object to split path to multiple equal parts.
After filling trail array object added call of trail calculating function.
lastTrailAdd = now;
trail.add(pos.Copy());
if (trail.size() > TRAIL_MAX_COUNT) {
trail.remove();
}
FillTrail();
Then my FillTrail function.
private void FillTrail() {
trailPath.reset();
boolean isFirst = true;
for(Point p : trail) {
if(isFirst) {
trailPath.moveTo(p.x, p.y);
trailPoss[0][0] = p.x;
trailPoss[0][1] = p.y;
isFirst = false;
} else {
trailPath.lineTo(p.x, p.y);
}
}
PathMeasure path = new PathMeasure(trailPath, false);
float step = path.getLength() / TRAIL_DRAW_POINT;
for(int i=0; i<TRAIL_DRAW_POINT; i++) {
path.getPosTan(step * i, trailPoss[i], trailTans[i]);
}
}
It separated from drawing thread. Next code is drawing function.
private void DrawTrail(Canvas canvas) {
if(trail.size() > 1) {
float prevWidthHalfX = 0f, prevWidthHalfY = 0f, prevX = 0f, prevY = 0f;
Path trailStepRect = new Path();
boolean isFirst = true;
for (int i = 0; i < TRAIL_DRAW_POINT; i++) {
float currWidthHalf = (float) (radius) * i / TRAIL_DRAW_POINT / 2f,
currWidthHalfX = currWidthHalf * trailTans[i][1],
currWidthHalfY = currWidthHalf * trailTans[i][0],
currX = trailPoss[i][0], currY = trailPoss[i][1];
if (!isFirst) {
trailStepRect.reset();
trailStepRect.moveTo(prevX - prevWidthHalfX, prevY + prevWidthHalfY);
trailStepRect.lineTo(prevX + prevWidthHalfX, prevY - prevWidthHalfY);
trailStepRect.lineTo(currX + currWidthHalfX, currY - currWidthHalfY);
trailStepRect.lineTo(currX - currWidthHalfX, currY + currWidthHalfY);
canvas.drawPath(trailStepRect, trailPaints[i]);
} else {
isFirst = false;
}
prevX = currX;
prevY = currY;
prevWidthHalfX = currWidthHalfX;
prevWidthHalfY = currWidthHalfY;
}
}
}
Main point of this is drawing trail by parts with different paints. Closer to ball - wider the trail. I think I will optimise it, but it is allready work.
If you want to watch how it looks just install my app from google play.
I'm writing an application to generate QR codes with custom dot shapes. What's the best way to do this using zxing?
So far, I've dug through the source code and I see that the data bits are written in com.google.zxing.qrcode.encoder.MatrixUtil.embedDataBits(). I think I could add some code on to the end of this function which would allow me to mask the dots but I'm not sure how to do this in Java. I can't extend the class because it's declared as final. Would it be a good idea and if so how would I extend this method in that way?
The other option I've been looking at involves post-processing the image produced by QRCode but this is really complex I think as I'd have to find a way to discern the dots from the positioning squares.
Is there a better way to do what I'm looking to do? Is there another QR code library besides zxing which can do what I'm looking to do out of the box?
P.S. I want to note that this is not a duplicate of this question although the keywords are similar.
The following java code uses zxing to make a QR-code image with circular dots and a circular finder pattern (custom rendering style). This can be adapted to other custom render styles.
I use the Encoder class directly and bypass QRCodeWriter and MatrixToImageWriter to gain enough control to alter the rendering. To alter the finder pattern, I use the fact that the finder pattern is always 7 dots wide/tall. Otherwise I would have to create a custom version of MatrixUtil (and perhaps Encoder).
Example QR Code Image Generated:
public static void main(String[] args) {
try {
generateQRCodeImage("https://www.google.com", 300, 300, "./MyQRCode.png");
} catch (Exception e) {
e.printStackTrace();
}
}
private static void generateQRCodeImage(String text, int width, int height, String filePath) throws WriterException, IOException {
final Map<EncodeHintType, Object> encodingHints = new HashMap<>();
encodingHints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
QRCode code = Encoder.encode(text, ErrorCorrectionLevel.H, encodingHints);
BufferedImage image = renderQRImage(code, width, height, 4);
try (FileOutputStream stream = new FileOutputStream(filePath)) {
stream.write(bufferedImageToBytes(image));
}
}
private static BufferedImage renderQRImage(QRCode code, int width, int height, int quietZone) {
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
Graphics2D graphics = image.createGraphics();
graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
graphics.setBackground(Color.white);
graphics.clearRect(0, 0, width, height);
graphics.setColor(Color.black);
ByteMatrix input = code.getMatrix();
if (input == null) {
throw new IllegalStateException();
}
int inputWidth = input.getWidth();
int inputHeight = input.getHeight();
int qrWidth = inputWidth + (quietZone * 2);
int qrHeight = inputHeight + (quietZone * 2);
int outputWidth = Math.max(width, qrWidth);
int outputHeight = Math.max(height, qrHeight);
int multiple = Math.min(outputWidth / qrWidth, outputHeight / qrHeight);
int leftPadding = (outputWidth - (inputWidth * multiple)) / 2;
int topPadding = (outputHeight - (inputHeight * multiple)) / 2;
final int FINDER_PATTERN_SIZE = 7;
final float CIRCLE_SCALE_DOWN_FACTOR = 21f/30f;
int circleSize = (int) (multiple * CIRCLE_SCALE_DOWN_FACTOR);
for (int inputY = 0, outputY = topPadding; inputY < inputHeight; inputY++, outputY += multiple) {
for (int inputX = 0, outputX = leftPadding; inputX < inputWidth; inputX++, outputX += multiple) {
if (input.get(inputX, inputY) == 1) {
if (!(inputX <= FINDER_PATTERN_SIZE && inputY <= FINDER_PATTERN_SIZE ||
inputX >= inputWidth - FINDER_PATTERN_SIZE && inputY <= FINDER_PATTERN_SIZE ||
inputX <= FINDER_PATTERN_SIZE && inputY >= inputHeight - FINDER_PATTERN_SIZE)) {
graphics.fillOval(outputX, outputY, circleSize, circleSize);
}
}
}
}
int circleDiameter = multiple * FINDER_PATTERN_SIZE;
drawFinderPatternCircleStyle(graphics, leftPadding, topPadding, circleDiameter);
drawFinderPatternCircleStyle(graphics, leftPadding + (inputWidth - FINDER_PATTERN_SIZE) * multiple, topPadding, circleDiameter);
drawFinderPatternCircleStyle(graphics, leftPadding, topPadding + (inputHeight - FINDER_PATTERN_SIZE) * multiple, circleDiameter);
return image;
}
private static void drawFinderPatternCircleStyle(Graphics2D graphics, int x, int y, int circleDiameter) {
final int WHITE_CIRCLE_DIAMETER = circleDiameter*5/7;
final int WHITE_CIRCLE_OFFSET = circleDiameter/7;
final int MIDDLE_DOT_DIAMETER = circleDiameter*3/7;
final int MIDDLE_DOT_OFFSET = circleDiameter*2/7;
graphics.setColor(Color.black);
graphics.fillOval(x, y, circleDiameter, circleDiameter);
graphics.setColor(Color.white);
graphics.fillOval(x + WHITE_CIRCLE_OFFSET, y + WHITE_CIRCLE_OFFSET, WHITE_CIRCLE_DIAMETER, WHITE_CIRCLE_DIAMETER);
graphics.setColor(Color.black);
graphics.fillOval(x + MIDDLE_DOT_OFFSET, y + MIDDLE_DOT_OFFSET, MIDDLE_DOT_DIAMETER, MIDDLE_DOT_DIAMETER);
}
Maven dependency:
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>core</artifactId>
<version>3.4.0</version>
</dependency>
I ended up forking zxing and using JitPack to include it with Maven. I implemented functionality for RGB masking and for drawing circles and outlined squares as dot shapes. Here is the repository: https://github.com/flotwig/zxing
I've recently started my first libGDX game, and it is all going well, everything renders fine but after about a minute nothing renders, the rendering calls are still made and the spritebatch works fine, I'm just left with a black screen, I have even changed the 'glClearColor()' to but I'm still left with a black screen. I've have no idea what this could be.
My main class:
#Override
public void create() {
Gdx.graphics.setDisplayMode(Settings.screenWidth, Settings.screenHeight, Settings.fullscreen);
Gdx.graphics.setVSync(Settings.VSync);
Gdx.graphics.setTitle("Trench Warfare");
batch = new SpriteBatch(1000);
previous = System.currentTimeMillis();
currentMap = new Map(this, 0);
currentMap.addObject(new ColourMapObject(this, 0));
}
private void update() {Settings.screenHeight, Settings.fullscreen);
Gdx.graphics.setVSync(Settings.VSync);
batch.setColor(new Color(Settings.brightness, Settings.brightness, Settings.brightness, 1.0f));
float delta = ((float)(System.currentTimeMillis() - previous)) / 1000.0f;
previous = System.currentTimeMillis();
currentMap.update(delta);
}
#Override
public void render() { //Always called
update();
Gdx.gl.glClearColor(1, 0, 0, 1); //Red colour still black screen.
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
batch.begin();
currentMap.render(batch); //Basicly list of textures to be rendered, they never stop rendering (Being called) despite black screen.
batch.end();
batch.flush();
}
EDIT:
We've determined that after some time SpriteBatch render a black screen over the red clear colour, It also stops rendering the texture.
I've also determined that the SpriteBatch's tint or colour stays white even during the black screen.
EDIT, this code takes in a texture and then turns into a different texture with different colours:
public class ColourMapObject extends MapObject {
public enum Type {
Dirt,
Water,
Trench,
}
private Texture terrainMap;
private Texture trenchMap;
private Texture soldierMap;
private Texture buildingMap;
private Texture shipMap;
private int levelId;
private Texture finalTexture;
private Type[][] types;
public ColourMapObject(TrenchMain main, int levelId) {
super(main);
this.levelId = levelId;
//finalTexture = new Texture("/map" + String.valueOf(levelId) + "/terrainMap.png");
finalTexture = new Texture("black.png");
finalTexture.getTextureData().prepare();
loadMap(levelId);
}
private void loadMap(int levelId) {
//terrainMap = new Texture("/map" + String.valueOf(levelId) + "/terrainMap.png");
terrainMap = new Texture("terrainMap.png");
types = new Type[terrainMap.getWidth()][terrainMap.getHeight()];
terrainMap.getTextureData().prepare();
Pixmap pixmap = terrainMap.getTextureData().consumePixmap();
for(int x = 0; x < terrainMap.getWidth(); x++) {
for(int y = 0; y < terrainMap.getHeight(); y++) {
types[x][y] = RandomMapColour.getType(new Color(pixmap.getPixel(x, y)));
if(types[x][y] == null) types[x][y] = Type.Dirt;
}
}
// trenchMap = new Texture("/map" + String.valueOf(levelId) + "/trenchMap.png");
//
//
// soldierMap = new Texture("/map" + String.valueOf(levelId) + "/soldierMap.png");
//
//
// buildingMap = new Texture("/map" + String.valueOf(levelId) + "/buildingMap.png");
//
//
// shipMap = new Texture("/map" + String.valueOf(levelId) + "/shipMap.png");
}
#Override
public void update(float delta) {
super.update(delta);
Pixmap draw = new Pixmap(Settings.screenWidth, Settings.screenHeight, Format.RGB888);
float pX = (float)terrainMap.getWidth() / (float)draw.getWidth();
float pY = (float)terrainMap.getHeight() / (float)draw.getHeight();
for(int x = 0; x < draw.getWidth(); x++) {
for(int y = 0; y < draw.getHeight(); y++) {
switch(types[(int)((float)x * pX)][(int)((float)y * pY)]) {
case Dirt:
draw.drawPixel(x, y, RandomMapColour.getDirtColour());
break;
case Trench:
draw.drawPixel(x, y, RandomMapColour.getTrenchColour());
break;
case Water:
draw.drawPixel(x, y, RandomMapColour.getWaterColour());
break;
}
}
}
finalTexture = new Texture(draw);
}
#Override
public void render(SpriteBatch batch) {
super.render(batch);
float sx = ((float)TrenchMain.getScreenWidth()) / ((float)finalTexture.getWidth());
float sy = ((float)TrenchMain.getScreenHeight()) / ((float)finalTexture.getHeight());
batch.draw(finalTexture, 0, 0, 0, 0, finalTexture.getWidth(), finalTexture.getHeight(), sx, sy, 0, 0, 0, finalTexture.getWidth(), finalTexture.getHeight(), false, false);
}
I finally figuired it out, for those who are wonder, what I was doing was creating a new finalTexture every update with disposing of the old one.
Simply dispose of the texture.
finalTexture.dispose();
In my cocos2d-android game app, there is a projectile, target and a ship, if projectiles and targets intersect both will disappear this works fine but when target falls on ship(intersect) ship is not getting removed, i tried searching in google but could not solve the issue, please help me if anyone knows this.
here's the code for it
public class GameL extends CCLayer{
protected LinkedList<CCSprite> _ships;
protected LinkedList<CCSprite> _targets;
protected LinkedList<CCSprite> _projectiles;
//protected int _projectilesDestroyed;
protected int _shipDestroyed;
protected CCSprite _player;
protected CCSprite _nextProjectile;
protected CCSprite ship;
public static CCScene scene()
{
CCScene scene = CCScene.node();
CCLayer layer = new GameL();
scene.addChild(layer);
return scene;
}
protected GameL()
{
this.setIsTouchEnabled(true);
_ships = new LinkedList<CCSprite>();
_targets = new LinkedList<CCSprite>();
_projectiles = new LinkedList<CCSprite>();
//_projectilesDestroyed = 0;
_shipDestroyed = 0;
CCSprite background = CCSprite.sprite("bg.png");
background.setTag(1);
background.setAnchorPoint(0, 0);
addChild(background);
Context context = CCDirector.sharedDirector().getActivity();
CGSize winSize = CCDirector.sharedDirector().displaySize();
_player = CCSprite.sprite("gun2.png");
_player.setPosition(CGPoint.ccp(65,120));
// _player.setPosition(CGPoint.ccp(_player.getContentSize().width/2.0f, winSize.height/2.0f));
addChild(_player);
CCSprite ship = CCSprite.sprite("ship150.png");
ship.setPosition(CGPoint.ccp(25,100));
ship.setAnchorPoint(CGPoint.ccp(0,0));
ship.setTag(4);
addChild(ship);
this.schedule("gameLogic", 1.0f);
this.schedule("update");
}
#Override
public boolean ccTouchesEnded(MotionEvent event)
{
// Choose one of the touches to work with
CGPoint location = CCDirector.sharedDirector().convertToGL(CGPoint.ccp(event.getX(), event.getY()));
// Set up initial location of projectile
CGSize winSize = CCDirector.sharedDirector().displaySize();
CCSprite _nextProjectile = CCSprite.sprite("firebl.png");
//_nextProjectile.setPosition(20, winSize.height / 2.0f);
_nextProjectile.setPosition(CGPoint.ccp(65, 120));
// Determine offset of location to projectile
int offX = (int)(location.x - _nextProjectile.getPosition().x);
int offY = (int)(location.y - _nextProjectile.getPosition().y);
// Bail out if we are shooting down or backwards
if (offX <= 0)
return true;
_nextProjectile.setTag(2);
// Determine where we wish to shoot the projectile to
int realX = (int)(winSize.width + (_nextProjectile.getContentSize().width / 2.0f));
float ratio = (float)offY / (float)offX;
int realY = (int)((realX * ratio) + _nextProjectile.getPosition().y);
CGPoint realDest = CGPoint.ccp(realX, realY);
// Determine the length of how far we're shooting
int offRealX = (int)(realX - _nextProjectile.getPosition().x);
int offRealY = (int)(realY - _nextProjectile.getPosition().y);
float length = FloatMath.sqrt((offRealX * offRealX) + (offRealY * offRealY));
float velocity = 480.0f / 1.0f; // 480 pixels / 1 sec
float realMoveDuration = length / velocity;
// Move projectile to actual endpoint
_nextProjectile.runAction(CCSequence.actions(
CCMoveTo.action(realMoveDuration, realDest),
CCCallFuncN.action(this, "spriteMoveFinished")));
// Determine angle to face
double angleRadians = Math.atan((double)offRealY / (double)offRealX);
double angleDegrees = Math.toDegrees(angleRadians);
double cocosAngle = -1 * angleDegrees;
double rotationSpeed = 0.5 / Math.PI;
double rotationDuration = Math.abs(angleRadians * rotationSpeed);
_player.runAction(CCSequence.actions(
CCRotateTo.action((float)rotationDuration, (float)cocosAngle),
CCCallFunc.action(this, "finishShoot")));
// Pew!
Context context = CCDirector.sharedDirector().getActivity();
SoundEngine.sharedEngine().playEffect(context, R.raw.pew_pew_lei);
return true;
}
public void finishShoot()
{
addChild(_nextProjectile);
_projectiles.add(_nextProjectile);
}
public void gameLogic(float dt)
{
addTarget();
}
public void update(float dt)
{
LinkedList<CCSprite> projectilesToDelete = new LinkedList<CCSprite>();
for (CCSprite projectile : _projectiles)
{
CGRect projectileRect = CGRect.make(projectile.getPosition().x - (projectile.getContentSize().width / 2.0f),
projectile.getPosition().y - (projectile.getContentSize().height / 2.0f),
projectile.getContentSize().width,
projectile.getContentSize().height);
LinkedList<CCSprite> targetsToDelete = new LinkedList<CCSprite>();
for (CCSprite target : _targets)
{
CGRect targetRect = CGRect.make(target.getPosition().x - (target.getContentSize().width),
target.getPosition().y - (target.getContentSize().height),
target.getContentSize().width,
target.getContentSize().height);
if (CGRect.intersects(projectileRect, targetRect))
targetsToDelete.add(target);
}
LinkedList<CCSprite> shipsToDelete = new LinkedList<CCSprite>();
for (CCSprite ship : _ships)
{
CGRect shipRect = CGRect.make(ship.getPosition().x - (ship.getContentSize().width),
ship.getPosition().y - (ship.getContentSize().height),
ship.getContentSize().width,ship.getContentSize().height);
for (CCSprite target : _targets)
{
CGRect targetRect = CGRect.make(target.getPosition().x - (target.getContentSize().width),
target.getPosition().y -
(target.getContentSize().height),
target.getContentSize().width,target.getContentSize().height);
if (CGRect.intersects(targetRect, shipRect))
{
shipsToDelete.add(ship);
break;
}
}
}
for (CCSprite target : targetsToDelete)
{
_targets.remove(target);
removeChild(target, true);
}
if (targetsToDelete.size() > 0)
projectilesToDelete.add(projectile);
for (CCSprite ship : shipsToDelete)
{
_ships.remove(ship);
removeChild(ship, true);
}
}
for (CCSprite projectile : projectilesToDelete)
{
_projectiles.remove(projectile);
removeChild(projectile, true);
if (_shipDestroyed > 0)
{
_shipDestroyed = 0;
CCDirector.sharedDirector().replaceScene(Gameoverlayer.scene("You Win!"));
}
}
}
protected void addTarget()
{
Random rand = new Random();
CCSprite target = CCSprite.sprite("fireball.png");
// Determine where to spawn the target along the Y axis
CGSize winSize = CCDirector.sharedDirector().displaySize();
int minX = (int)(target.getContentSize().width / 2.0f);
int maxX = (int)(winSize.width - target.getContentSize().width / 2.0f);
int rangeX = maxX - minX;
int actualX = rand.nextInt(rangeX) + minX;
// Create the target slightly off-screen along the right edge,
// and along a random position along the Y axis as calculated above
// target.setPosition(getContentSize().width + (target.getContentSize().width / 2.0f), actualX);
target.setPosition(actualX, winSize.height + target.getContentSize().height);
addChild(target);
target.setTag(1);
_targets.add(target);
// Determine speed of the target
int minDuration = 2;
int maxDuration = 4;
int rangeDuration = maxDuration - minDuration;
int actualDuration = rand.nextInt(rangeDuration) + minDuration;
// Create the actions
//CCMoveTo actionMove = CCMoveTo.action(actualDuration, CGPoint.ccp(-target.getContentSize().width / 2.0f, actualX));
CCMoveTo actionMove = CCMoveTo.action(actualDuration, CGPoint.ccp(actualX, - target.getContentSize().height));
CCCallFuncN actionMoveDone = CCCallFuncN.action(this, "spriteMoveFinished");
CCSequence actions = CCSequence.actions(actionMove, actionMoveDone);
target.runAction(actions);
}
public void spriteMoveFinished(Object sender)
{
CCSprite sprite = (CCSprite)sender;
if (sprite.getTag() == 1)
{
_targets.remove(sprite);
_shipDestroyed = 0;
//CCDirector.sharedDirector().replaceScene(Gameoverlayer.scene("You Lose :("));
}
else if (sprite.getTag() == 2)
_projectiles.remove(sprite);
this.removeChild(sprite, true);
}
}
Are you sure the rects you use to detect the collision are correct ? As far as I know the default anchor point for sprites is {0.5;0.5}, so the rect calculation would be more like :
CGRect shipRect = CGRect.make(ship.getPosition().x - (ship.getContentSize().width / 2),
ship.getPosition().y - (ship.getContentSize().height / 2),
ship.getContentSize().width,ship.getContentSize().height);
In the effort to learn more about applets and Java, I am experimenting making wave applets by drawing lines (drawLine) and making animated line graphs.
I can make a static graph just fine. However I am struggling with the animated aspect of the graph: the axes of the graph should move from left to right, increasing and growing larger than 0.
My problem is translating my needs into a solution. Can anyone give me any pointers with my problem?
I have a multidimensional array indexed by points containing the x and y of a particular point. I have tried modifying my render function to decrease the Xs to make it appear as if it is moving left but this doesn't work right.
What approach am I looking to take? How different will my approach be if the values of Y could change due to user action or added data?
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.Random;
/**
* A graph that should in the future represent a wave according to my inputs
*
* #authorImprofane
* #version 1
*/
public class Graph extends JFrame
{
private InnerGraph inner;
private int width;
private Random RNG;
private int height;
private int[][] series;
private int xoffset;
int prevx = 0;
int prevy = 0;
/**
* Constructor for objects of class Graph
*/
public Graph(int width, int height) throws InterruptedException
{
RNG = new Random();
setTitle(" Graph");
series = new int[width][2];
this.width = width;
this.height = height;
inner = new InnerGraph(width, height);
add(inner, BorderLayout.CENTER);
setVisible(true);
inner.preparePaint();
pack();
updateGraph();
}
public static void main(String[] args) throws InterruptedException
{
new Graph(300, 300);
}
public void updateGraph() throws InterruptedException
{
// virtual x is how far along on the x axis we are, I ignore the 'real' X axis
int vx = 0;
int point = 0;
int xdecay = 0;
int inc = 5;
// how many times we need to plot a point
int points = (int) java.lang.Math.floor( width / inc );
System.out.println(points);
inner.preparePaint();
// draw all points to graph
// make some junk data, a saw like graph
for (vx = 0 ; vx < points ; vx++) {
series[vx] = new int[] { vx*inc, ( (vx*inc) % 120 ) };
}
Thread.sleep(150);
int n = 5;
while(n > 0) {
System.out.println(xdecay);
inner.preparePaint();
for (vx = 0 ; vx < points ; vx++) {
inner.updateSeries(vx, xdecay);
inner.repaint();
Thread.sleep(50);
}
xdecay += inc;
// shift the data points to the left
int[][] nseries = new int[points][2];
// System.arraycopy(series, 1, nseries, 0, points-1);
n--;
}
}
public class InnerGraph extends JPanel
{
private Graphics g;
private Image img;
private int gwidth;
private int gheight;
Dimension size;
public InnerGraph(int width, int height)
{
gwidth = width;
gheight = height;
size = new Dimension(1, 1);
}
/**
* Try make panel the requested size.
*/
public Dimension getPreferredSize()
{
return new Dimension(gwidth, gheight);
}
/**
* Create an image and graphics context
*
*/
public void preparePaint()
{
size = getSize();
img = inner.createImage( (size.width | gwidth), (size.height | gheight) );
g = img.getGraphics();
}
/**
* Draw a point to the chart given the point to use and the decay.
* Yes this is bad coding style until I work out the mathematics needed
* to do what I want.
*/
public void updateSeries(int point, int decay)
{
g.setColor(Color.blue);
int nx = series[point][0];
series[point][0] -= decay;
if ( point-1 >= 0 ) {
series[point-1][0] -= decay;
}
int ny = series[point][1];
prevx -= decay;
g.drawLine(prevx-decay, prevy, nx-decay, ny );
prevx = nx-decay;
prevy = ny;
}
public void paintComponent(Graphics g)
{
g.drawImage(img, 0, 0, null);
}
}
}
First, it looks like you are subtracting the decay too often in the updateSeries method.
Below is a new version of that method.
public void updateSeries(int point, int decay)
{
g.setColor(Color.blue);
int nx = series[point][0];
series[point][0] -= decay;
if ( point-1 >= 0 ) {
series[point-1][0] -= decay;
}
int ny = series[point][1];
// prevx -= decay;
// g.drawLine(prevx-decay, prevy, nx-decay, ny );
g.drawLine(prevx, prevy, nx-decay, ny );
prevx = nx-decay;
prevy = ny;
}
With those changes, the lines draw better, but they draw so slowly that the animation is hard to see. You probably need to build a new graphics and swap the whole thing so that you don't have to watch each individual line segment being drawn.
For a starter you could check out the following example (and the ones related to this)
Scroll Chart #java2s.com