Set certain position of FlxSprite's loadgraphic method - haxe

I have a 122 * 16 image.
It has seven colors, and I use only one color per block.
But, loadGraphic() in the FlxSprite class just uses width and height.
How do I use certain position of image?
For example, if I choose 0, loadGraphic() picks up the position width, height(0 to 15, 16), choose 1, (17 ~ 31, 16)

Could you use an animation but change the current frame manually? Something like this:
var sprite = new FlxSprite(100, 100);
sprite.loadGraphic("assets/image.png", true, 122, 16);
sprite.animation.add("my_animation", [0, 1, 2, 3, 4, 5, 6], 0, false);
sprite.animation.play("my_animation", true, 0);
//sprite.animation.paused = true;
sprite.animation.frameIndex = 2; // The frame you want to display

Related

Game dev -Finding img sprites coords Haxe + Haxeflixel

I'm trying to make a combat system in haxe I made my sprites and now I need to find out the uv coordinates for them how do I achieve that ?
Example from my existing code :
animation.add("lr", [3, 4, 3, 5], 6, false);
animation.add("u", [6, 7, 6, 8], 6, false);
animation.add("d", [0, 1, 0, 2], 6, false);
I tried :
if (FlxG.mouse.justPressed) {
// Attack code here
}
Haxeflixel's sprite sheet system doesn't use UV coordinates, it assumes all sprites in the sheet are the same size and consistently spaced apart.
Look at the API reference for FlxSprite.loadGraphic. The animation tutorial uses that function like this:
loadGraphic(AssetPaths.player__png, true, 16, 16);
This means the sprites are in a 16x16 grid, and they're indexed from left to right, top to bottom (with the left-most being index 0).
Here's a visual example of how the coordinates map to indices:
And here's that same sprite, but with two rows instead of one:
Compare those indices to the values in the sample code:
animation.add("lr", [3, 4, 3, 5], 6, false);
animation.add("u", [6, 7, 6, 8], 6, false);
animation.add("d", [0, 1, 0, 2], 6, false);
The second parameter to add is an array of indices that make up the animation.
So to add a punch animation, just put the frames into the existing grid, and reference them using their indices in the overall spritesheet.
As far as implementing a "combat system", that's a more involved thing. If you just want to play an attack animation, you can make it a non-looping animation, and use a callback function to detect when it ends. Example:
//...defined somewhere in your sprite class
var is_punching:Bool = false;
//...somewhere inside your constructor maybe
animation.finishCallback = function(name:String){
switch(name){
case "punch-u", "punch-lr", "punch-d":
is_punching = false;
default:
trace("Some other animation finished: " + name);
}
}
//...somewhere in your update function
if (FlxG.mouse.justPressed && !is_punching) {
is_punching = true;
switch (facing)
{
case LEFT, RIGHT:
animation.play("punch-lr");
case UP:
animation.play("punch-u");
case DOWN:
animation.play("punch-d");
case _:
}
}
Then you can check if is_punching is true to prevent the player from walking while punching, or to damage an enemy if they collide with the player while they're punching.

How to return the last index of a group in a list Python

I have a list in following form:
[0, 0, 0, 0, 1, 1, 1, 0.6, 0.6, 0, 0, 0]
each of the items in the list is a small decimal number. I'm looking for a way of returning the last index position of each group. In the above example it would be something like:
0: 3, 1: 6, 0.6: 8, 0: 11
I'm fairly new to python and I don't really know how to approach this
itertools.groupby may be useful here, it deals with pretty much everything except tracking the indices which isn't hard to do yourself:
import itertools
a = [0, 0, 0, 0, 1, 1, 1, 0.6, 0.6, 0, 0, 0]
i = 0
for val, group in itertools.groupby(a):
for inst in group:
# each element that is the same in sequence, increment index
i += 1
# after the inner for loop i will be the index of the first element of next group
# so i - 1 is the index of last occurence.
print(val, i - 1)
If you are particularly clever with enumerate and variable unpacking you can make this super short although less obvious how it's working.
import itertools
from operator import itemgetter
a = [0, 0, 0, 0, 1, 1, 1, 0.6, 0.6, 0, 0, 0]
# still group only by value but now use enumerate to have it keep track of indices
for val, group in itertools.groupby(enumerate(a), itemgetter(1)):
# this is tuple unpacking, irrelevant is a list of values that aren't the last one, and last is the one we care about.
[*irrelevent, last] = group
print(last)
This answer is less intended to say "here's how you should do it" and more "this is some of the things that exist in python", happy coding :)
Try this :
a=[0, 0, 0, 0, 1, 1, 1, 0.6, 0.6, 0, 0, 0]
i=0
while(i<=len(a)):
if (i == len(a)-1):
print(str(a[i]) + ":" + str(i))
break
if(a[i]!=a[i+1]):
print(str(a[i])+":"+str(i))
i=i+1

Finding the position of the median of an array containing mostly zeros

I have a very large 1d array with most elements being zero while nonzero elements are all clustered around some few islands separated by many zeros: (here is a smaller version of that for the purpose of a MWE)
In [1]: import numpy as np
In [2]: A=np.array([0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,3,6,20,14,10,5,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,4,5,5,18,18,16,14,10,2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,2,3,3,6,16,4,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0])
I want to find the median and its position (even approximately) in terms of the index corresponding to the median value of each island. Not surprisingly, I am getting zero which is not what I desire:
In [3]: np.median(A)
Out[3]: 0.0
In [4]: np.argsort(A)[len(A)//2]
Out[4]: 12
In the case of a single island of nonzero elements, to work around this caveat and meet my requirement that only nonzero elements are physically meaningful, I remove all zeros first and then take the median of the remaining elements:
In [5]: masks = np.where(A>0)
In [6]: A[masks]
Out[6]: array([ 1, 3, 6, 20, 14, 10, 5, 1])
This time, I get the median of the new array correctly, however the position (index) would not be correct as it is evident and also pointed out in the comments as being ill-defined mathematically.
In [7]: np.median(A[masks])
Out[7]: 5.5
In [8]: np.argsort(A[masks])[len(A[masks])//2]
Out[8]: 2
According to this approximation, I know that real median is located in the third index of the modified array but I would like to translate it back into the format of the original array where the position (index) of the median should be somewhere in the middle of the first island of the nonzero elements corresponding to a larger index (where indices of zeros are all counted correctly). Also answered in the comments are two suggestions made to come up with the position of the median given one island of nonzero elements in the middle of a sea of zeros. But what if there is more than one such island? How could possibly one calculate the index corresponding to median of each island in the context of the original histogram array where zeros are all counted?
I am wondering if there is any easy way to calculate the position of the median in such arrays of many zeros. If not, what else should I add to my lines of code to make that possible after knowing the position in the modified array? Your help is great appreciated.
Based on the comment "A is actually a discrete histogram with many bins", I think what you want is the median of the values being counted. If A is an integer array of counts, then an exact (but probably very inefficient, if you have values as high as 1e7) formula for the median is
np.median(np.repeat(np.arange(len(A)), A)) # Do not use if A contains very large values!
Alternatively, you can use
np.searchsorted(A.cumsum(), 0.5*A.sum())
which will be the integer part of the median.
For example:
In [157]: A
Out[157]:
array([ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 3,
6, 20, 14, 10, 5, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0])
In [158]: np.median(np.repeat(np.arange(len(A)), A))
Out[158]: 35.5
In [159]: np.searchsorted(A.cumsum(), 0.5*A.sum())
Out[159]: 35
Another example:
In [167]: B
Out[167]:
array([ 0, 0, 0, 1, 100, 21, 8, 3, 2, 1, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])
In [168]: np.median(np.repeat(np.arange(len(B)), B))
Out[168]: 4.0
In [169]: np.searchsorted(B.cumsum(), 0.5*B.sum())
Out[169]: 4

How to obtain the indices of all maximum values in array A that correspond to unique values in array B?

Suppose one has an array of observation times ts, each of which corresponds to some observed value in vs. The observation times are taken to be the number of elapsed hours (starting from zero) and can contain duplicates. I would like to find the indices that correspond to the maximum observed value per unique observation time. I am asking for the indices as opposed to the values, unlike a similar question I asked several months ago. This way, I can apply the same indices on various arrays. Below is a sample dataset, which I would like to use to adapt a code for a much larger dataset.
import numpy as np
ts = np.array([0, 0, 1, 2, 3, 3, 3, 4, 4, 5, 6, 7, 8, 8, 9, 10])
vs = np.array([500, 600, 550, 700, 500, 500, 450, 800, 900, 700, 600, 850, 850, 900, 900, 900])
My current approach is to split the array of values at any points at which there is not a duplicate time.
condition = np.where(np.diff(ts) != 0)[0]+1
ts_spl = np.split(ts, condition)
vs_spl = np.split(vs, condition)
print(ts_spl)
>> [array([0, 0]), array([1]), array([2]), array([3, 3, 3]), array([4, 4]), array([5]), array([6]), array([7]), array([8, 8]), array([9]), array([10])]
print(vs_spl)
>> [array([500, 600]), array([550]), array([700]), array([500, 500, 450]), array([800, 900]), array([700]), array([600]), array([850]), array([850, 900]), array([900]), array([900])]
In this case, duplicate max values at any duplicate times should be counted. Given this example, the returned indices would be:
[1, 2, 3, 4, 5, 8, 9, 10, 11, 13, 14, 15]
# indices = 4,5,6 correspond to values = 500, 500, 450 ==> count indices 4,5
# I might modify this part of the algorithm to return either 4 or 5 instead of 4,5 at some future time
Though I have not yet been able to adapt this algorithm for my purpose, I think it must be possible to exploit the size of each previously-split array in vs_spl to keep an index counter. Is this approach feasible for a large dataset (10,000 elements per array before padding; 70,000 elements per array after padding)? If so, how can I adapt it? If not, what are some other approaches that may be useful here?
70,000 isn't that insanely large, so yes it should be feasible. It is, however, faster to avoid the splitting and use the .reduceat method of relevant ufuncs. reduceat is like reduce applied to chunks, but you don't have to provide the chunks, just tell reduceat where you would have cut to get them. For example, like so
import numpy as np
N = 10**6
ts = np.cumsum(np.random.rand(N) < 0.1)
vs = 50*np.random.randint(10, 20, (N,))
#ts = np.array([0, 0, 1, 2, 3, 3, 3, 4, 4, 5, 6, 7, 8, 8, 9, 10])
#vs = np.array([500, 600, 550, 700, 500, 500, 450, 800, 900, 700, 600, 850, 850, 900, 900, 900])
# flatnonzero is a bit faster than where
condition = np.r_[0, np.flatnonzero(np.diff(ts)) + 1, len(ts)]
sizes = np.diff(condition)
maxima = np.repeat(np.maximum.reduceat(vs, condition[:-1]), sizes)
maxat = maxima == vs
indices = np.flatnonzero(maxat)
# if you want to know how many maxima at each hour
nmax = np.add.reduceat(maxat, condition[:-1])

gles v2 newbie wants to draw a line

i'm an old glBegin() programmer and i need to port this structure
struct Line { float color[3]; float vertices[2][3];};
to a more new drawing paradigm.
how to draw this with glDrawArrays or glDrawElements, supposed that shaders are ok?
thank you, mic.
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 3, lines->vertices);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 3, lines->color);
glDrawElements(GL_LINES, 2, GL_UNSIGNED_SHORT, line_indices);
Assuming you've assigned your vertex shader's 'position' and 'color' vertex attributes to 0 and 1. Indices array should be something like GLshort indices[] = { 0, 1 };.

Resources