I have this method here which renders my players movement. It swaps between 3 images, standing, left leg forward, and right leg forward.
It swaps images very fast so how can I change the speed of the rendering?
public static void renderUpwardWalking() {
ImageIcon[] frames = { CharacterSheet.up, CharacterSheet.upLeftLeg,
CharacterSheet.upRightLeg };
if (Key.up && Character.direction == "up") {
currentFrame++;
if (currentFrame == 3)
currentFrame = 1;
Character.character.setIcon(frames[currentFrame]);
} else if (!Key.up && Character.direction == "up") {
currentFrame = 0;
}
}
This is usually done on timer.
Decide on a frame pattern and a frequency. You seem to have chosen the frame pattern CharacterSheet.up, CharacterSheet.upLeftLeg, CharacterSheet.upRightLeg. Let's say you want to swap frame every 400 ms.
Get the time from a clock with sufficient resolution. System.nanoTime() is usually accurate enough.
long frameTime = 400L * 1000000L; // 400 ms in nanoseconds Edit
currentFrame = (System.nanoTime() / frametime) % frames.length;
You can change the scale of your currentFrame counter, and use its range to control your frame rate:
//Let this go from 1...30
int currentFrameCounter;
.
.
.
currentFrameCounter++;
if(currentFrameCounter == 30) currentFrameCounter = 0;
//Take a fraction of currentframeCounter for frame index ~ 1/10 frame rate
//Note care to avoid integer division
currentFrame = (int) (1.0*currentFrameCounter / 10.0);
Putting it all together in a general model:
int maxCounter = 30; //or some other factor of 3 -- controls speed
int currentFrameCounter;
public static void renderUpwardWalking() {
ImageIcon[] frames = { CharacterSheet.up, CharacterSheet.upLeftLeg,
CharacterSheet.upRightLeg };
if (Key.up && Character.direction == "up") {
currentFrameCounter++; //add
if(currentFrameCounter == maxCounter) currentFrameCounter = 0;
currentFrame = (int) (1.0*currentFrameCounter / (maxCounter/3.0));
Character.character.setIcon(frames[currentFrame]);
} else if (!Key.up && Character.direction == "up") {
currentFrame = 0;
}
}
Related
I am wondering how the ListView estimates the height/width of it's contentItem, though the delegate is a Component that you can't ask, and the size might vary from one delegate-instance to another.
It does not use the average size of the current instances.
Otherwise in Example 1, if one element is pressed, the estimated size would be 3055.5 if all instances are counted, or 3125 if only those in the view are counted. It estimates 2845
It does not use the maximums size of all current instances.
If one element is pressed, the estimated size would be 7500. If the maximum height is only considered for non-instantiated elements, it would be 6350
It does not use the minimum size of all current instances.
The estimation would be definitely to small.
And even if you know the right size, you can't help it, for in Example 1 we know the correct contentHeight would be 2500 if nothing is pressed, and 2650 if something is pressed. In Example 2 the right contentHeight would be 1225 but setting manually setting the value is of no use, as it is overwritten soon after.
Example 1:
ListView {
id: lv1
width: 200
height: 500
model: 50
onContentHeightChanged: console.log('estimated contentHeight', contentHeight)
delegate: Rectangle {
width: 200
height: ma.pressed ? 150 : 50
border.color: 'black'
Text {
anchors.centerIn: parent
text: index
}
MouseArea {
id: ma
anchors.fill: parent
}
}
}
Example 2:
ListView {
id: lv1
width: 200
height: 500
model: 50
onContentHeightChanged: console.log('estimated contentHeight', contentHeight)
delegate: Rectangle {
width: 200
height: index
border.color: 'black'
Text {
anchors.centerIn: parent
text: index + ' ' + ((index * (index + 1)) / 2)
}
}
}
I don't know. Let's look through the source code. :)
Looking at the code, here's where the contentWidth and contentHeight are set:
void QQuickItemViewPrivate::updateViewport()
{
Q_Q(QQuickItemView);
qreal extra = headerSize() + footerSize();
qreal contentSize = isValid() || !visibleItems.isEmpty() ? (endPosition() - startPosition()) : 0.0;
if (layoutOrientation() == Qt::Vertical)
q->setContentHeight(contentSize + extra);
else
q->setContentWidth(contentSize + extra);
}
The startPosition() and endPosition() functions are declared here:
qreal QQuickItemViewPrivate::startPosition() const
{
return isContentFlowReversed() ? -lastPosition() : originPosition();
}
qreal QQuickItemViewPrivate::endPosition() const
{
return isContentFlowReversed() ? -originPosition() : lastPosition();
}
QQuickListView's implementations of originPosition() and lastPosition() are both here:
qreal QQuickListViewPrivate::originPosition() const
{
qreal pos = 0;
if (!visibleItems.isEmpty()) {
pos = (*visibleItems.constBegin())->position();
if (visibleIndex > 0)
pos -= visibleIndex * (averageSize + spacing);
}
return pos;
}
qreal QQuickListViewPrivate::lastPosition() const
{
qreal pos = 0;
if (!visibleItems.isEmpty()) {
int invisibleCount = INT_MIN;
int delayRemovedCount = 0;
for (int i = visibleItems.count()-1; i >= 0; --i) {
if (visibleItems.at(i)->index != -1) {
// Find the invisible count after the last visible item with known index
invisibleCount = model->count() - (visibleItems.at(i)->index + 1 + delayRemovedCount);
break;
} else if (visibleItems.at(i)->attached->delayRemove()) {
++delayRemovedCount;
}
}
if (invisibleCount == INT_MIN) {
// All visible items are in delayRemove state
invisibleCount = model->count();
}
pos = (*(--visibleItems.constEnd()))->endPosition();
if (invisibleCount > 0)
pos += invisibleCount * (averageSize + spacing);
} else if (model && model->count()) {
pos = (model->count() * averageSize + (model->count()-1) * spacing);
}
return pos;
}
averageSize seems to be calculated here:
void QQuickListViewPrivate::updateAverage()
{
if (!visibleItems.count())
return;
qreal sum = 0.0;
for (int i = 0; i < visibleItems.count(); ++i)
sum += visibleItems.at(i)->size();
averageSize = qRound(sum / visibleItems.count());
}
That function is called by QQuickListViewPrivate::visibleItemsChanged(), which is called by QQuickItemViewPrivate::refill(), which is called... all over the place. Basically whenever anything related to the view or its items changes.
visibleItems.at(i)->size() is pretty much equivalent to QQuickItem::width()/QQuickItem::height():
inline qreal itemWidth() const { return item ? item->width() : 0; }
inline qreal itemHeight() const { return item ? item->height() : 0; }
From what I can see, it more or less takes the height of every item that is visible (could probably be equated with "currently instantiated") in the view, adds them together and then divides that sum by the number of visible items. You can confirm this by adding the following debug output:
$ git diff
diff --git a/src/quick/items/qquicklistview.cpp b/src/quick/items/qquicklistview.cpp
index 0351077..acfb88a 100644
--- a/src/quick/items/qquicklistview.cpp
+++ b/src/quick/items/qquicklistview.cpp
## -1296,6 +1296,7 ## void QQuickListViewPrivate::updateAverage()
for (FxViewItem *item : qAsConst(visibleItems))
sum += item->size();
averageSize = qRound(sum / visibleItems.count());
+ qDebug() << "sum" << sum << "visibleItems.count()" << visibleItems.count();
}
qreal QQuickListViewPrivate::headerSize() const
The output of this before clicking an item:
qml: estimated contentHeight 5000
sum 550 visibleItems.count() 11
qml: estimated contentHeight 2500
sum 850 visibleItems.count() 17
After pressing on the first item:
sum 850 visibleItems.count() 15
qml: estimated contentHeight 2845
So I would say that
It does not use the average size of the current instances.
is incorrect to some degree. If you really want to know what the difference is, you'll need to look further into the code.
int x = 31;
int y = 31;
int x_dir = 4;
int y_dir = 0;
void setup ()
{
size (800, 800);
}
void draw ()
{
background (150);
ellipse (x,y,60, 60);
if (x+30>=width)
{
x_dir =-4;
y_dir = 4;
}
if (y+30>=height)
{
x_dir=4;
y_dir = 0;
}
if (x+30>=width)
{
x_dir = -4;
}
x+=x_dir;
y+=y_dir;
println(x,y);
}
Hi,
I have to create this program in processing which produces an animation of a ball going in a Z pattern (top left to top right, diagonal top right to bottom left, and then straight from bottom left to bottom right) which then goes backwards along the same path it came.
While I have the code written out for the forward direction, I don't know what 2 if or else statements I need to write for the program so that based on one condition it goes forwards, and based on another condition it will go backwards, and it will continue doing so until it terminates.
If I am able to figure out which two if statements I need to write, all I need to do is copy and reverse the x_dir and y_dir signs on the forward loop.
There are a ton of different ways you can do this.
One approach is to keep track of which "mode" you're in. You could do this using an int variable that's 0 when you're on the first part of the path, 1 when you're on the second part of the path, etc. Then just use an if statement to decide what to do, how to move the ball, etc.
Here's an example:
int x = 31;
int y = 31;
int mode = 0;
void setup ()
{
size (800, 800);
}
void draw ()
{
background (150);
ellipse (x, y, 60, 60);
if (mode == 0) {
x = x + 4;
if (x+30>=width) {
mode = 1;
}
} else if (mode == 1) {
x = x - 4;
y = y + 4;
if (y+30>=height) {
mode = 2;
}
} else if (mode == 2) {
x = x + 4;
if (x+30>=width) {
mode = 3;
}
} else if (mode == 3) {
x = x - 4;
y = y - 4;
if (y-30 < 0) {
mode = 2;
}
}
}
Like I said, this is only one way to approach the problem, and there are some obvious improvements you could make. For example, you could store the movement speeds and the conditions that change the mode in an array (or better yet, in objects) and get rid of all of the if statements.
I have created a Space Invaders game in which the player must shoot an asteroid which displays a random number. A sum will also be randomly generated at the start of the scene. Once the player shoots an asteroid the scene reloads, with points awarded for correct answers.
The problem I am having is that I need at least one asteroid to display the correct answer. I am currently achieving this by reloading the scene until an asteroids number matches the answer to the sum. This can take quite a few reloads and looks really bad. Is there a better way to achive this which will look better and be more efficient. I have included my effort below. I appreciate any comments. Thanks!
Script for checking the correct answer and reloading the scene.
#pragma strict
function Start ()
{
}
{
if (
Asteroid1_Script.asteroid1Value != (Sum_Script.sumA - Sum_Script.sumB) &&
Asteroid2_Script.asteroid2Value != (Sum_Script.sumA - Sum_Script.sumB) &&
Asteroid3_Script.asteroid3Value != (Sum_Script.sumA - Sum_Script.sumB) &&
Asteroid4_Script.asteroid4Value != (Sum_Script.sumA - Sum_Script.sumB) &&
Asteroid5_Script.asteroid5Value != (Sum_Script.sumA - Sum_Script.sumB)
)
{
Application.LoadLevel("L1");
}
}
Script for randomly generating the sum.
#pragma strict
static var sumA :int = 0;
static var sumB :int = 0;
function Start ()
{
var newSumA = Random.Range(6,10);
sumA = newSumA;
var newSumB = Random.Range(1,6);
sumB = newSumB;
}
function Update () {
//Question Output.
guiText.text = sumA.ToString() + " - " + sumB.ToString()+ " =";
}
Script for generating an asteroids random number.
#pragma strict
var mainCam: Camera;
static var asteroid1Value : int = 0;
var asteroid1 : Transform;
var Asteroid1Style : GUIStyle;
function Start ()
{
var newAsteroid1Value = Random.Range(0,10);
asteroid1Value = newAsteroid1Value;
asteroid1.position.x = mainCam.ScreenToWorldPoint (new Vector3 (160f, 0f, 0f)).x;
asteroid1.position.y = mainCam.ScreenToWorldPoint (new Vector3 (0f, 450f, 0f)).y;
}
function OnGUI()
{
var point = Camera.main.WorldToScreenPoint(transform.position);
GUI.Label(new Rect(point.x, Screen.currentResolution.height - point.y - 530, 110, 100), asteroid1Value.ToString(), Asteroid1Style);
}
function OnCollisionEnter(col : Collision)
{
if(asteroid1Value == (Sum_Script.sumA - Sum_Script.sumB))
{
Destroy(gameObject);
Score_Script.score ++;
}
if(asteroid1Value != (Sum_Script.sumA - Sum_Script.sumB))
{
Score_Script.score --;
}
}
Do as you are doing, generate 5 random numbers for your asteroids.
Then generate a random number between 1 and 5, this is your random asteroid, and then set its value to the answer. (sumA - sumB)
You just need to abstract your logic.
The best argument I can make is, simply put, build your random numbers before you build your asteroids.
That way, you always have a correct one.
I would simply code:
function start(){
var x = 5 //X being whatever number of asteroids you wish.
var a = new Array();
for(var i=0; i<x; i++){
a[i] = Random.Range(0,10);
}
for( i in a){ buildAsteroid(a[i]) }
}
And... if the number matches, success.
I am developing an XNA game that is using Kinect. The player seen on the screen is the real image of the person who is playing in front of Kinect sensor. For eliminating the background and getting only the player's image I am doing these operations in kinect.AllFramesReady:
using (ColorImageFrame colorVideoFrame = imageFrames.OpenColorImageFrame())
{
if (colorVideoFrame != null)
{
//Getting the image of the colorVideoFrame to a Texture2D named colorVideo
}
//And setting its information on a Color array named colors with GetData
colorVideo.GetData(colors);
}
using (DepthImageFrame depthVideoFrame = imageFrames.OpenDepthImageFrame())
{
if (depthVideoFrame != null){
//Copying the the image to a DepthImagePixel array
//Using only the pixels with PlayerIndex > 0 to create a Color array
//And then setting the colors of this array from the 'colors' array by using MapDepthPointToColorPoint method, provided by Kinect SDK
//Finally I use SetData function in order to set the colors to a Texture2D I created before
}
}
But the performance is very low unsurprisingly. Because I have to use GetData for a color array with 640*480 = 307200 length (because of the ColorImageFormat) and SetData for another color array with 320*480 = 76800 length (because of the DepthImageFormat) in every frame!
I wonder if there is any other solutions for this problem, any alternatives for SetData and GetData maybe. Because I know that these functions moving data between the GPU and CPU and that is an expensive operation for big data. Thanks for any help.
The Kinect for Windows Toolbox comes with a "GreenScreen-WPF" example, which should provide some insight into processing the information. Because you are working in XNA there may be some differences, but the overall concepts should work between the two examples.
The example works by extracting multiple players. Here is the business end of the processing function:
private void SensorAllFramesReady(object sender, AllFramesReadyEventArgs e)
{
// in the middle of shutting down, so nothing to do
if (null == this.sensor)
{
return;
}
bool depthReceived = false;
bool colorReceived = false;
using (DepthImageFrame depthFrame = e.OpenDepthImageFrame())
{
if (null != depthFrame)
{
// Copy the pixel data from the image to a temporary array
depthFrame.CopyDepthImagePixelDataTo(this.depthPixels);
depthReceived = true;
}
}
using (ColorImageFrame colorFrame = e.OpenColorImageFrame())
{
if (null != colorFrame)
{
// Copy the pixel data from the image to a temporary array
colorFrame.CopyPixelDataTo(this.colorPixels);
colorReceived = true;
}
}
// do our processing outside of the using block
// so that we return resources to the kinect as soon as possible
if (true == depthReceived)
{
this.sensor.CoordinateMapper.MapDepthFrameToColorFrame(
DepthFormat,
this.depthPixels,
ColorFormat,
this.colorCoordinates);
Array.Clear(this.greenScreenPixelData, 0, this.greenScreenPixelData.Length);
// loop over each row and column of the depth
for (int y = 0; y < this.depthHeight; ++y)
{
for (int x = 0; x < this.depthWidth; ++x)
{
// calculate index into depth array
int depthIndex = x + (y * this.depthWidth);
DepthImagePixel depthPixel = this.depthPixels[depthIndex];
int player = depthPixel.PlayerIndex;
// if we're tracking a player for the current pixel, do green screen
if (player > 0)
{
// retrieve the depth to color mapping for the current depth pixel
ColorImagePoint colorImagePoint = this.colorCoordinates[depthIndex];
// scale color coordinates to depth resolution
int colorInDepthX = colorImagePoint.X / this.colorToDepthDivisor;
int colorInDepthY = colorImagePoint.Y / this.colorToDepthDivisor;
// make sure the depth pixel maps to a valid point in color space
// check y > 0 and y < depthHeight to make sure we don't write outside of the array
// check x > 0 instead of >= 0 since to fill gaps we set opaque current pixel plus the one to the left
// because of how the sensor works it is more correct to do it this way than to set to the right
if (colorInDepthX > 0 && colorInDepthX < this.depthWidth && colorInDepthY >= 0 && colorInDepthY < this.depthHeight)
{
// calculate index into the green screen pixel array
int greenScreenIndex = colorInDepthX + (colorInDepthY * this.depthWidth);
// set opaque
this.greenScreenPixelData[greenScreenIndex] = opaquePixelValue;
// compensate for depth/color not corresponding exactly by setting the pixel
// to the left to opaque as well
this.greenScreenPixelData[greenScreenIndex - 1] = opaquePixelValue;
}
}
}
}
}
// do our processing outside of the using block
// so that we return resources to the kinect as soon as possible
if (true == colorReceived)
{
// Write the pixel data into our bitmap
this.colorBitmap.WritePixels(
new Int32Rect(0, 0, this.colorBitmap.PixelWidth, this.colorBitmap.PixelHeight),
this.colorPixels,
this.colorBitmap.PixelWidth * sizeof(int),
0);
if (this.playerOpacityMaskImage == null)
{
this.playerOpacityMaskImage = new WriteableBitmap(
this.depthWidth,
this.depthHeight,
96,
96,
PixelFormats.Bgra32,
null);
MaskedColor.OpacityMask = new ImageBrush { ImageSource = this.playerOpacityMaskImage };
}
this.playerOpacityMaskImage.WritePixels(
new Int32Rect(0, 0, this.depthWidth, this.depthHeight),
this.greenScreenPixelData,
this.depthWidth * ((this.playerOpacityMaskImage.Format.BitsPerPixel + 7) / 8),
0);
}
}
If you are interested in only a single player, you could look into using the player mask to more quickly extract the appropriate pixel set. You'd fi
using (SkeletonFrame skeletonFrame = e.OpenSkeletonFrame())
{
if (skeletonFrame != null && skeletonFrame.SkeletonArrayLength > 0)
{
if (_skeletons == null || _skeletons.Length != skeletonFrame.SkeletonArrayLength)
{
_skeletons = new Skeleton[skeletonFrame.SkeletonArrayLength];
}
skeletonFrame.CopySkeletonDataTo(_skeletons);
// grab the tracked skeleton and set the playerIndex for use pulling
// the depth data out for the silhouette.
this.playerIndex = -1;
for (int i = 0; i < _skeletons.Length; i++)
{
if (_skeletons[i].TrackingState != SkeletonTrackingState.NotTracked)
{
this.playerIndex = i+1;
}
}
}
}
You can then step through the depth data to extract the appropriate bits:
depthFrame.CopyPixelDataTo(this.pixelData);
for (int i16 = 0, i32 = 0; i16 < pixelData.Length && i32 < depthFrame32.Length; i16++, i32 += 4)
{
int player = pixelData[i16] & DepthImageFrame.PlayerIndexBitmask;
if (player == this.playerIndex)
{
// the player we are tracking
}
else if (player > 0)
{
// a player, but not the one we want.
}
else
{
// background or something else we don't care about
}
}
I'm pulling this code from a control I use to produce a silhouette, so it does not deal with the color stream. However, making a call to MapDepthFrameToColorFrame at the appropriate time should allow you to deal with the color stream data and extract the corresponding pixels to the player's mask.
My question perhaps belongs to general ability test or something like that. It is not directly related to Embedded devices.
I have been given a variable resister which can rotate infinitely and is of 10Ω. ADC is set for value range 0 to 1023 sampling. By which I've to control light luminosity/intensity.
The ADC value range is divided into 32 steps for 1024/32 levels of brightness. The issue is the pot has to be rotated 16 times to get to extremities. Which is very harassing. Now its time when I can't change the pot hardware but the firmware.
I thought of doing as follows, please help me from here:
I'll choose a range window within the [0 1023], say of 32 steps. Lets ignore the ADC noise for now.
Then we have 32 steps in that 32 step windows.
If I start from 0, the intensity will be increasing till 32. The 32 is max intensity possible. Then if I rotate more, the intensity should remain maximum at 32 all the way till 1023.
And as soon as it is started to decrease from 1023, I will have decrease in intensity till ( 1023-32 ) and will remain at 0 intensity all the way till 0.
if I rotate back from any place it should follow the above explained moving window rule.
How to start with it?
Pseudo code:
void processADC_data()
{
ushort adc0 = (ushort)ADC_DATA;
adc0_Avg = adc0;
// If Noise
/*
ushort adc0_L = (ushort)(adc0 - 40);
ushort adc0_H = (ushort)(adc0 + 40);
adc0 = (ushort)read_ADC( adc0_L,adc0_H );
adc0_Avg = adc0 * 20 + adc0_Avg * 80;
adc0_Avg /= 100;
*/
IsInceasing = (adc0_last - adc0_Avg) < 0 ;
adc0_last = adc0_Avg;
if (IsInceasing)
{
// Extrimity has to be handled
if (!HasPerformedIncreased)
{
adc0_center = (ushort)(adc0_Avg - window);
HasPerformedIncreased = true;
HasPerformedDecrease = false;
}
else if (HasPerformedIncreased)
{
IsCrossingLimit = ( (adc0_Avg - adc0_center) > window );
if(IsCrossingLimit)
{
adc0_Avg = LIGHT_SENS_MAX;
IsCrossingLimit = false;
}
else
{
adc0_Avg = (ushort)(adc0_Avg / LIGHT_SENS_MAX);
}
}
//judge_brightness(adc0_Avg);
}
else
{
// Extrimity has to be handled
if (!HasPerformedDecrease)
{
adc0_center = (ushort)(adc0_Avg + window);
HasPerformedDecrease = true;
HasPerformedIncreased = false;
}
else if (HasPerformedDecrease)
{
IsCrossingLimit = ( (adc0_center - adc0_Avg) > window );
if(IsCrossingLimit)
{
adc0_Avg = LIGHT_SENS_MIN;
IsCrossingLimit = false;
}
else
{
adc0_Avg = (ushort)(adc0_Avg / LIGHT_SENS_MAX);
}
}
}
brightness(adc0_Avg);
}
Thanks