I am currently trying out the Timeline class in JavaFX 2.2. The API-Documentation states that the Timeline
processes individual KeyFrame sequentially, in the order specified by KeyFrame.time
So i thought i could create a SequentialTransition-like animation by putting some KeyFrame objects in a specific order into the TimeLine. Each KeyFrame has its own Duration. Thats where my problems start: what is Duration? The offset at which the KeyFrame should start or the "real" duration that the KeyFrame takes to animate? I think the API is not very clear at that point.
Have a look at this code:
Group g = new Group();
Circle c = new Circle(15);
c.setTranslateX(150);
c.setTranslateY(150);
g.getChildren().add(c);
Timeline tl = new Timeline();
KeyValue kv1 = new KeyValue(c.scaleXProperty(), 5);
KeyValue kv2 = new KeyValue(c.scaleYProperty(), 5);
KeyFrame kf1 = new KeyFrame(Duration.millis(1500), kv1,kv2);
KeyValue kv3 = new KeyValue(c.centerXProperty(), 200);
KeyFrame kf2 = new KeyFrame(Duration.millis(5000), kv3);
tl.getKeyFrames().addAll(kf1,kf2);
tl.play();
primaryStage.setScene(new Scene(g,500,500));
primaryStage.show();
My goal is to show the "grow"-animation of KeyFrame kf1 first, then the "move"-animation of kf2. The code starts the animation of every KeyFrame at the same time (t=0s), but with different lengths (because Duration is set different).
So is there any way to change this behaviour so that the KeyFrames are "played" in a sequential order?
KeyFrames represent instants ("Frames") in the animation. The time parameter represents not a duration but the instant on the timeline when that frame occurs; you can perhaps think of it as the duration since the start of the timeline. The timeline extends from time zero to the maximum time of all its KeyValues, and it interpolates the values of the properties defined in all its KeyFrames between those Frames.
So your code creates a timeline of length 5 seconds. It interpolates the centerX to move from 0 to 200 over those 5 seconds, and the scaleX and scaleY properties to increase from 1 to 5 over the first 1.5 seconds.
To define the sequential behavior you are looking for, use a SequentialTransition:
KeyValue kv1 = new KeyValue(c.scaleXProperty(), 5);
KeyValue kv2 = new KeyValue(c.scaleYProperty(), 5);
KeyFrame kf1 = new KeyFrame(Duration.millis(1500), kv1,kv2);
Timeline grow = new Timeline();
grow.getKeyFrames().add(kf1);
KeyValue kv3 = new KeyValue(c.centerXProperty(), 200);
KeyFrame kf2 = new KeyFrame(Duration.millis(5000), kv3);
Timeline move = new Timeline();
move.getKeyFrames().add(kf2);
SequentialTransition sequence = new SequentialTransition(grow, move);
sequence.play();
You could replace the two Timelines with a ScaleTransition and a TranslateTransition if you wanted.
Related
I'm working on a game where a level is separated into rooms where the camera is confined into the current room, meaning the camera wont "bleed" into adjacent ones. A room is a scene RoomBase consisting of Positions RoomLimitTopLeft and RoomLimitBottomRight (which define the camera's limits) and an Area2D which detects when the player enters the room. As each room's size and exits will wary, I created a script which streches the Area2D's CollisionShape to the rooms's size.
RoomBase.gd
const ROOM_TRANS_LIMIT = 16
onready var limit_tl = $RoomLimitTopLeft # Position
onready var limit_br = $RoomLimitBottomRight # Position
onready var room_transition = $RoomTransition # Area2D
onready var room_transition_coll = $RoomTransition/CollisionShape2D
func setRoomTransition():
var width = limit_br.position.x - limit_tl.position.x - 2*ROOM_TRANS_LIMIT
var height = limit_br.position.y - limit_tl.position.y - 2*ROOM_TRANS_LIMIT
self.room_transition.position = Vector2(limit_br.position.x/2, limit_br.position.y/2)
self.room_transition_coll.shape.set_extents(Vector2(width/2, height/2))
This code centers the Area2D's position to its room and stretches its collision to cover almost the whole room, which works fine with only one room. However, if a level consists of multiple rooms, the most recent room instance overwrites the collision shape of the previous ones. For example, if Room 1 is horizontal and Room 2 is vertical, then Room 1 will share 2's vertical collision shape.
Is it possible to change an individual scene instances collisions without affecting any others?
you could also change the setting of the node, if possible, in the Inspector
I'm not sure if this is the issue, but for what I understand you are using the same Shape2D for every room. If all they are all using the same Shape2D, and you modify that Shape2D, the changes are reflected in all of them.
You can duplicate the Shape2D from code (or make it unique from the inspector). That way you have a different Shape2D.
I am using azure web job to save thumb of an image and this is code for doing this
ImageProcessor.Imaging.Formats.FormatBase f;
f = new ImageProcessor.Imaging.Formats.JpegFormat();
Size size = new Size(200, 200);
using (WebClient client = new WebClient())
{
MemoryStream stream = new MemoryStream(client.DownloadData(input));
MemoryStream stream2 = new MemoryStream();
int quality = 110;
do
{
quality = quality - 10;
using (ImageFactory factory = new ImageFactory(false))
{
factory.Load(stream)
.Format(f)
.Resize(size)
//.BackgroundColor(Color.White)
.Quality(quality)
.Save(stream2);
}
} while (stream2.Length > stream.Length || stream2.Length ==100000);
When i add message to queue with this image for example,
job should give me thumb image 200 * 200 but there is trailing black area in top and bottom of resulted image like this which shouldn't be done
Why this is done ???
You're trying to fit a rectangle into a square.
From http://imageprocessor.org/imageprocessor/imagefactory/resize/:
Resize
Resizes the current image to the given dimensions. If EXIF metadata is to be preserved the information contained within will also be updated to match.
public ImageFactory Resize(Size size)
Parameters
size:
The System.Drawing.Size containing the width and height to set the image to.
Passing a 0 for either dimension will omit that dimension.
So, pass in 0 as height to maintain aspect ratio,
Size size = new Size(200, 0);
or use one of the other resize modes: Crop/Min/Max/Stretch
I'm not sure how to flip the axes of my chart. Below is the code I'm using.
Please see also the picture on how it looks right now. Instead of drawing the data vertically I'd like to show it horizontally. It suppose to look like a stock chart because that is what it actually is. I'm using YQL to get the historical data of the symbol as Json format.
I also see the data is scooped in the whole screen. I'd like to see the last month for example and just allow the user to swipe to the right for more or just to zoom out.
I'd appreciate some help.
float vals=0;
String[] resultStrs = new String[StockHistoryArray.length()];
for (int i = 0; i < StockHistoryArray.length(); i++) {
JSONObject chartDataObj = StockHistoryArray.getJSONObject(i);
yVals.add(new Entry(vals,(int) Float.parseFloat(chartDataObj.getString("Adj_Close")),i+1));
xVals.add(i, String.valueOf(vals));
vals++;
}
LineDataSet setting = new LineDataSet(yVals, "Stock Chart");
ArrayList<ILineDataSet> dataSets = new
ArrayList<ILineDataSet>();
dataSets.add(setting);
LineData data = new LineData(xVals, dataSets);
lineChart.setData(data);
Legend l = lineChart.getLegend();
l.setForm(Legend.LegendForm.LINE);
l.setTextColor(Color.WHITE);
XAxis x1 = lineChart.getXAxis();
x1.setTextColor(Color.WHITE);
x1.setDrawGridLines(false);
x1.setAvoidFirstLastClipping(true);
YAxis y1 = lineChart.getAxisLeft();
y1.setTextColor(Color.WHITE);
y1.setAxisMaxValue(120f);
y1.setDrawGridLines(true);
return null;
Here is the screen shot after I run this code. It is one year history.
screen capture
You are doing wrong in the following line.
yVals.add(new Entry(vals,(int) Float.parseFloat(chartDataObj.getString("Adj_Close")),i+1));
Use like this to draw the chart correctly
yVals.add(new Entry(entryVal,entryXIndex);
If your value in chartDataObj.getString("Adj_Close")
then you need to add like this
yVals.add(new Entry(Float.parseFloat(chartDataObj.getString("Adj_Close")), i);
I want my display objects to move on the screen with a velocity and without any interactions. How can i do that with corona? Thanks.
First you have to add your display object to the physics, and then set its velocity to a random value. You can use a timer to periodically change the movement of the display object. For example:
physics = require("physics");
physics.start()
rectangle = display.newRect(0, 0, 50, 50)
physics.addBody(rectangle, "kinematic", {isSensor = true})
function moveRandomly()
rectangle:setLinearVelocity(math.random(-300,300), math.random(-300,300));
end
timer.performWithDelay(500, moveRandomly, -1);
I am using node.js and express, and I am calling server-side functions and syncing variables using nowjs. Suppose the user is drawn as a sprite on the canvas. His x,y coordinates are kept server-side in a "position" array.
Server-side:
position = { x : 0; y : 0 }
updatePosition = function (a,b)
{
playerPosition.x += a;
playerPosition.y += b;
}
Client-side:
if keypress('right'){ updatePosition(32,0); }
These are pseudocode. When the user presses the 'right' button, the server-side "updatePosition" function is called, which adds 32 (pixels) to the x-coordinate of the "position" array. This array is then shared with the client, and the new position is drawn on the canvas using client-side function.
Suppose I don't want to draw the sprite at the new position instantly. I want to play a walking animation that gradually moves the sprite 32 pixels to the right, and takes say 1 second to complete. I might implement it this way:
User presses the 'right' button.
The animation starts playing client-side.
updatePosition is called server-side as usual.
When animation on the client finishes, check if the final position client-side matches the coordinates stored server side.
When the user presses the 'right' button/key, he cannot repeat the keypress until 1 second later. The 1 second long "walking" animation has to complete and final position checked with the server-side coordinates before he can press 'right' again to move his sprite.
Question: How do I keep track of the 1 second server side? I can't do it client-side because the user will be able to hack his client to reduce the animation time.
Is the solution to "timestamp" the position array? E.g. position = { x : 0; y : 0, time: 0 }. If the user presses the 'right' button again, the server would check to see if the last position update was greater than 1 second ago. If less than 1 second, the server ignores it.
Why not simply storing a "lock" in the user session?
session.editLock = new Date().getTime();
When another edit is triggered by the client, just:
if(session.editLock && new Date().getTime() - session.editLock > 1000) {
// Return error
}
Modifying the position object doesn't feel right to me. A position object is meant to store position, not time.