Modifying parent classes variables - haxe

Iv looked around online for a solution to this issue but iv been unable to solve it.
I want to extend the sprite class to make my own interactive circle. Everything works but setting the X,Y, Width and height of the custom class does not work:
class CircleDraw extends Sprite
{
public function new(x:Int,y:Int,width:Int,height:Int)
{
super();
this.x = x;
this.y = y;
this.width = width;
this.height = height;
drawCircle();
}
private function drawCircle()
{
this.graphics.beginFill(0xffffff);
this.graphics.drawCircle(this.x,this.y, this.width);
this.graphics.endFill();
}
}
The approach above does not work as expected, setting x,y and width via the constructor results in literally nothing appearing. Yet if i set them manually, either within the class
this.graphics.drawCircle(200,200, 30);
Or prior to addChild:
circle = new CircleDraw(10,10,100,200);
circle.x=100;
circle.y=100;
it then appears on screen. also after adding it like so once the values have been added manually within the class rather than this.x etc:
circle = new CircleDraw(10,10,100,200);
addChild(circle);
So my question is this, how do i extend a class (Sprite) and allow the constructor to modify its parents default variables and keep the values?
EDIT
Just to provide all the code as requested:
This does not work:
circle = new CircleDraw(10,10,100,200);
addChild(circle);
when Circle draw is like this:
class CircleDraw extends Sprite
{
public function new(x:Int,y:Int,width:Int,height:Int)
{
super();
this.x = x;
this.y = y;
this.width = width;
this.height = height;
drawCircle();
}
private function drawCircle()
{
this.graphics.beginFill(0xffffff);
this.graphics.drawCircle(this.x, this.y, this.width);
this.graphics.endFill();
}
}
It does work if i modify the method:
private function drawCircle()
{
this.graphics.beginFill(0xffffff);
this.graphics.drawCircle(200, 200, 30);
this.graphics.endFill();
}
Or if during the instancing of the object i set the X and Y variables as mentioned before the edit.

You are indeed setting the base class variables successfully, it's just that DisplayObject.width has a rather specific (and perhaps not that obvious) behavior.
width:Float
Indicates the width of the display object, in pixels. The width is calculated based on the bounds of the content of the display object. When you set the width property, the scaleX property is adjusted accordingly, as shown in the following code:
Except for TextField and Video objects, a display object with no content(such as an empty sprite) has a width of 0, even if you try to set width to a different value.
—OpenFL API: DisplayObject: width
In this sense, OpenFL follows the ActionScript 3.0 API.

From what I can surmise, it looks like you're trying to override a constructor (new) that takes no arguments.
I'm not entirely sure, but that might not get you what you want. What I think you're actually doing is just creating a method "new" on the extended class, and then within it, feeding the parent nothing (super()). So the parent will not have the constructor arguments. It would be interesting to do look at that object in a debugger and look at the instance properties vs. the parent ones.
There's probably a way around that, but I think you might want to look at doing this via composition instead of inheritance. For example, in "new", create a new instance of a sprite, and manipulate the properties of that.
class MySprite
{
public var sprite : Sprite;
public function new ( ) {
sprite = new Sprite ();
}
}
You would then perform your operations on that sprite instance. Essentially, you are just wrapping a sprite in your own class. Decorator, more or less.
I found some reference to the topic here (it's been a while since I did any Flash programming), it shows addChild and removeChild implementations, etc.
http://old.haxe.org/forum/thread/685

From the (partial) code you posted, it looks it should work.
In other words, setting parent's variables like that should work.
I doubt there are some other code you didn't post gets in the way. I suggest you print out the x, y values in the drawCircle call to debug.
I also doubt the circle is drawn off-screen so you can't see it. Because you first moved the sprite, to (x,y) and then draw a circle in (x,y) inside the sprite. So effectively the circle is at (2x,2y) in global space
EDIT:
this.graphics.drawCircle(200,200, 30);
You claim this worked. Should draw at (210,210) with radius 30
circle = new CircleDraw(10,10,100,200);
circle.x=100;
circle.y=100;
You claim this worked. Should draw at (200,200) with radius 100
circle = new CircleDraw(10,10,100,200);
addChild(circle);
You claim this didn't work. Should draw at (20,20) with radius 100
From the above three version, you are actually drawing at different places with different sizes. So I still suspect that "didn't work" may due to the fact that you are drawing at some places not in sight.
So I still suggest you print out the value of x, y, width inside the private drawCircle function to see what's happening

Be aware, that you are kind of dealing with 2 coordinate spaces. The one were the Sprite will be added and the graphics object of that Sprite. If you set this.x and this.width you are actually setting properties of this Sprite. So in regards of positing you are moving the Sprite itself in that case. The Sprite "graphics" property has it's own coordinate space.
For example if you pass x=100 in your CircleDraw constructor function you are first moving the sprite itself by x=100 and then draw the circle with an x offset of 100. So if you would add the sprite directly to the Stage you would start drawing your circle actually at x=200, because you effectively applied the position twice. It seems to me this is not what you actually are intending.
Also your CircleDraw instance (which is also a Sprite of course) is "empty" when you are constructing it. So calling this.width = width in your constructor has no effect. this.width will stay 0 because the Sprite has no contents at that point. So in the drawCircle method you are drawing a circle with a width of 0.
Probably the better solution would be to simply pass the arguments of your constructor function to your drawCircle function, without setting any properties.

Related

Animation for a canvas object

I'm trying to use an animation for a sudoku app. I want for everytime i insert a wrong number, that number would change color and it's scale.
My code is:
override fun onDraw(canvas: Canvas?) {
canvas ?: return
drawBoard(canvas)
drawNumberProblem(canvas)
}
private fun drawNumberProblem(canvas: Canvas){
paint.color=darkcolor
paint.textSize = cellSide*3/4
SudokuGame.numbersproblem.forEach { e->
canvas.drawText("${e.number}", originX + e.col * cellSide+cellSide/5, originX + (e.row+1) * cellSide-cellSide/10, paint)
}
}
And i tried:
private fun initAnimation() {
var animation = RotateAnimation(0f, 360f, 150f, 150f)
animation.setRepeatCount(Animation.INFINITE)
animation.setRepeatMode(Animation.RESTART)
animation.setDuration(7500L)
animation.interpolator = LinearInterpolator()
startAnimation(animation)
}
override fun onDraw(canvas: Canvas?) {
canvas ?: return
if(animation==null)
initAnimation()
drawBoard(canvas)
drawNumberProblem(canvas)
}
private fun drawNumberProblem(canvas: Canvas){
paint.color=darkcolor
paint.textSize = cellSide*3/4
SudokuGame.numbersproblem.forEach { e->
canvas.drawText("${e.number}", originX + e.col * cellSide+cellSide/5, originX + (e.row+1) * cellSide-cellSide/10, paint)
}
}
The animation, the board and the numbers are all good. The animation is only an example, i tried to rotate it to see if it's working. But the only problem is that the animation is working for the whole board, i want to have animation only over numbers.
Is there any way to create a initAnimation with a parameter like initAnimation(drawNumberProblem())?
I am new to kotlin animation, so i don't really care about the best way to do it, i want to find a simple way to understand it.
Thanks
If each cell is its own View (say a TextView) you can animate it the way you're trying to, and the animation framework will take care of the timing, the rotation and scaling, etc. Because each view is separate, they can all be animated independently, using Android's view animation libraries, and a lot of the work is taken care of for you - it's pretty easy to use!
If it's all one view, and you're drawing a bunch of elements which can all be animated, you have to keep track of those elements, any animations that should be happening to each one, and how each animation's state affects the element when it comes time to draw it. Instead of each view having its own state and being drawn separately, you have to draw the whole thing at once, because it's a single view. So you need to keep track of those individual element states yourself, so you can refer to them when drawing the current overall state.
So for example, say you've got an animation where an element needs to scale to 2x the size and then back to normal, and it runs for 1 second total (1000ms). When you come to draw that element, you need to know how far along that animation you are at that moment, so you can scale it appropriately, and draw it at the correct size.
There are lots of ways to do this, probably some smarter ones, but this is the most basic hands-on example I think. I'm not testing this, but hopefully it gives you the idea:
// for brevity, so we can just say "now" instead of writing out the whole function call
val now: Long get() = System.currentTimeMillis()
// store a start time for each grid cell (or null if there's no anim running)
val animStartTimes = Array(CELL_COUNT)<Long?>
val animLength = 1000 // millis
// Basic function to start an animation - you could adapt this to prevent restarts
// while an anim is already running, etc
fun startAnim(cellIndex: Int) {
animStartTimes[cellIndex] = now
// tell the view it needs to redraw (since we're animating something now)
invalidate()
}
// Get the current progress of an animation in a cell, from 0% to 100% (0.0 to 1.0)
// I'm treating a finished item as "reset" to its original state
fun getAnimProgress(cellIndex: Int): Float {
val start = animStartTimes[cellIndex]
if (start == null) return 0f
val progress = (now - start) / animLength
if (progress > 1f) {
// animation has ended (past 100% of its runtime) so let's clear it
animStartTimes[cellIndex] = null
return 0f // like I said, I'm treating finished animations as "reset" to 0%
} else return progress
}
override fun onDraw(canvas: Canvas) {
// this flag can be set to true if we find an element that's still animating,
// so we can decide whether to call invalidate() again (forcing a redraw next frame)
var animating = false
items.forEachIndexed { i, item ->
val animProgress = getAnimProgress(i)
if (animProgress > 0f) animating = true // set that flag
// now you need to use that 0.0-1.0 value to calculate your animation state,
// e.g. adjusting the text size by some factor - 0.0 should produce your "default" state
}
// finally, force a redraw next frame if necessary - only do this when your view
// contents might need to change, otherwise you're wasting resources
if (animating) invalidate()
}
I hope that makes sense - obviously I haven't shown how to actually draw the states of your animation, that depends on exactly what you're doing - but that's the basics of it. It's a lot more work than using view animation, but it's not too bad when you get the idea.
The drawing part is a little more complex, and you'll probably want to get familiar with manipulating the Canvas - e.g. to draw a rotated character, you turn the canvas, draw the character as normal, then undo the canvas rotation so it's the right way up again, and the character is tilted. I don't have time to look for any tutorials about it, but this article covers the matrix operations that scale/rotate/etc the canvas
So yeah, it's a bit involved - and depending on what you want to do, a grid of TextViews might be a better shout

How to spawn solvers with initial orientation?

It seems very hard to get configured solvers to instantiate in a certain orientation like always in front of the SolverTarget. It seems you have to set the transforms values manually, the goal values of the SolverHandler and additionally call SnapTo on the Solver you're using because otherwise you have some kind of interpolation going on.
I'm trying this with a RadialView and it already takes me too long to get this right, rotation and all...
What's the correct way to do this the right way? Set position, rotation, done?
If the object with the RadialView was created at edit time and is active, it will snap its orientation as you've described.
Unfortunately, instantiating an object, or re-enabling an existing object with a solver will cause it to "solve" against its original position. I've found the easiest way to force the correct position is to set the lerp time to "0" for a single frame.
[SerializeField]
private GameObject objectWithSolver = null;
private IEnumerator InitialSolve(Solver solver)
{
float originalMoveLerp = solver.MoveLerpTime;
float originalRotateLerp = solver.RotateLerpTime;
solver.MoveLerpTime = 0.0f;
solver.RotateLerpTime = 0.0f;
yield return null;
solver.MoveLerpTime = originalMoveLerp;
solver.RotateLerpTime = originalRotateLerp;
}
void Update()
{
if (Input.GetKeyDown(KeyCode.J))
{
GameObject newObject = Instantiate(objectWithSolver);
newObject.SetActive(true);
StartCoroutine(InitialSolve(newObject.GetComponent<Solver>()));
}
}
That said, this sounds like a great feature request.

Over-riding the background() function in p5.js?

I made a galaxy sketch in p5.js using rotates and radians, but it's erased each time the background() is loaded as draw() runs. Is there a way to over-ride the background() function? I want the galaxies to remain in view.
var stars;
function preload(){
//for (var i = 0; i < planetArray.length; i++) {
//stars = loadImage('Assets/stars.png');
}
function setup(){
createCanvas(windowWidth, windowHeight);
}
function draw() {
//background(0);
star()
//function mousepressed(){
}
function star(){
//angle = map(mouseX, 0,width, 0,360);
//rotate(radians(angle*100));
noStroke();
//translate(width/2, height/2);
translate(mouseX,mouseY);
fill(0);
rotate(radians(frameCount%360)); //rotates output of ellipses
rotate(radians(1000*frameCount%360));
for(var i =0; i < 20; i++){
push();
noStroke();
fill(random(200),0,random(150),random(2));
// fill(random(125),random(250),random(100));
ellipse(10*frameCount % (width/10),0,10,10);
//image(stars, 10*frameCount % (width/2),0,10,10)
//image((10*frameCount % (width/2),0,10,10)
//
pop();
}
}
Well, there really isn't any magic to it. Calling the background() function fills the window with a solid color (or image) and draws over anything you've previously drawn.
The solution to this problem isn't to "over-ride" the background() function. It's to restructure your program so your stuff gets drawn properly. Exactly how you do that depends on exactly what you want to happen.
Option 1: Only call the background() function once.
If you just want a black background at the beginning, and everything you do from the draw() function should still add up, then maybe you just want to call the background() function once. You could do it as the last line in your setup() function, for example.
Option 2: Store everything you want to draw in a data structure.
This is probably the most typical case. If you want a background to be drawn behind shapes that are moving around, you're going to have to store those shapes in some kind of data structure, and then draw all of them every single frame.
Option 3: Draw to an off-screen image, and then draw that image on top of your background.
This is a bit of a mix between the first two options. You can draw everything (except the background) to an off-screen PImage, and then draw the background to the screen, then draw the image to the screen. This allows you to have a background that changes colors without having to redraw everything else.
Which option you choose really depends on exactly what you want to happen.

Creating UI dynamically in android

I want to make UI for tablet like shown in images.This UI will repeat according to number of items. And the position of each block (i.e small or big block) can change dynamically. Please give me suggestion which view,layout i should use.
Any suggestion would be appreciated...thanks in advance.
If you are targeting a API v14 or above, you can use GridLayout: http://developer.android.com/reference/android/widget/GridLayout.html
Using LinearLayout where each category is added and using RelativeLayout for each category is a good option. You should customize onlayout method of the relative layout as a function of number of products it contains.
You can use fragments, listview as well.
EDIT after image change: You can just extend relativelayout and override onLayout method. This will perform better than nested layouts and I can't think of anything else you can get away with less effort.
EDIT for elaboration:
Here is an example class I use. Basically in the onlayout method you make every decision and tell all the child views to lay them in a rectangle by calling layout method of each of them and passing the parameters of the rectangle. See how I use layout method of child view to dictate the rectangle.
public class KnockPile extends HandPile
{
private static final String TAG = "KnockPile";
static final int EXPECTED_CARDS = 3;
int mColoring; // this is the coloring group this pile is associated with.
// every card added to this pile should be set with this color.
public KnockPile(Context context, GameActivity ref , int ingroup)
{
super(context );
mColoring = ingroup;
mActivityReference = ref;
setWillNotDraw(false);
setClickable(true);
setOnDragListener(this);
mCardBorders = new ArrayList<Integer>();
final LayoutTransition transition = new LayoutTransition();
setLayoutTransition(transition );
//transition .enableTransitionType(LayoutTransition.CHANGING);
//transition .disableTransitionType(LayoutTransition.CHANGE_APPEARING);
}
/**
* this overrides the card ordering of handpile. This method lays the cards in a linear fashion.
* Possibly overlapping fashion. This is not dependent to orientation of screen.
*
* #see com.kavhe.kondi.gin.layouts.HandPile#onLayout(boolean, int, int, int, int)
*/
#Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
int availablewidth = getMeasuredWidth() ;//this is the maximum availlable
int distance = availablewidth /Math.max(getChildCount(), 1) ; // the horizontal distance between two cards
Log.v(TAG,"available width onlayout is :" + availablewidth +"and distance is " + distance);
int cardheight = getHeight();
int cardwidth = cardheight*3/4;
if(distance > cardwidth) distance = cardwidth;
mCardBorders.clear();
for(int i = 0 ; i < mCards.size() ; i++)
{
//save this border into a global variable so that it can be used when one of the cards dragged
//by user to show that user can insert to that location
mCardBorders.add( i*distance);
mCards.get(i).layout( i*distance , 0 , cardwidth+ i*distance , cardheight);
}
}
}
and this is from documentation
protected void onLayout (boolean changed, int left, int top, int right, int bottom)
Called from layout when this view should assign a size and position to each of its children. Derived classes with children should override this method and call layout on each of their children.
Parameters
changed This is a new size or position for this view
left Left position, relative to parent
top Top position, relative to parent
right Right position, relative to parent
bottom Bottom position, relative to parent
It is also possible through table layout with its row span property
Are the "products" always going to fit nicely on lines as you have drawn? If then, you can use LinearLayouts (Vertical and Horizontal) nested in each other.
To design such UIs for Tablets you should use Fragments and inside the fragment add/remove your respective layouts. If you are taking Relative Layouts then proper usage of RelativeLayout.LayoutParams is required.
If you are looking for a best example which uses Fragments try Google IO app source. It uses various dynamic UI features.
Hope it helps !
With the help of StaggeredGridView I sloved my requirement.
Thanks to all for help and support.

unity3d: how to make a SpotLight follow an object?

I am making an object move in it's update() and turn left right up down according to user input. All I want is to make a spotlight follow the object.
Object's Rotation: 0,180,0
SpotLight's Rotation: 90,0,0
Since the rotations are different( and they need to be like that), I cannot make the light follow the object.
code :
function Update () {
SetControl(); // Input Stuff...
transform.Translate (0, 0, objectSpeed*Time.deltaTime);
lightView.transform.eulerAngles=this.transform.eulerAngles;
lightView.transform.Rotate=this.transform.eulerAngles;
lightView.transform.Translate(snakeSpeed*Time.deltaTime,0, 0); //THIS IS INCORRECT
}
lightView is simply pointing to the SpotLight.
What your looking for is the Unity method Transform.lookAt.
Place the following script on the spotlight. This code will make the object it is attached to, look at another object.
// Drag another object onto it to make the camera look at it.
var target : Transform;
// Rotate the camera every frame so it keeps looking at the target
function Update() {
transform.LookAt(target);
}
All I want is to make a spotlight follow the object.
This is a two-step process. First, find the coordinate position (in world coordinates) of your target. Second, apply that position plus an offset to your spotlight. Since your light is rotated 90° along the x-axis, I assume your light is above and looking down.
var offset = new Vector3(0, 5, 0);
function Update()
{
// Move this object
transform.Translate (0, 0, objectSpeed*Time.deltaTime);
// Move the light to transform's position + offset.
// Note that the light's rotation has already been set and does
// not need to be re-set each frame.
lightView.transform.position = transform.position + offset;
}
If you want a smoother "following" action, do a linear interpolation over time. Replace
lightView.transform.position = transform.position + offset;
with
lightView.transform.position = Vector3.Lerp(lightView.transform.position, transform.position + offset, Time.deltaTime * smoothingFactor);
where smoothingFactor is any float.
As an aside, it is near death to call transform.* in any kind of recurring game loop, because GameObject.transform is actually a get property that does a component search. Most Unity documentation recommends you cache the transform variable first.
Better code:
var myTrans = transform; // Cache the transform
var lightTrans = lightView.transform;
var offset = new Vector3(0, 5, 0);
function Update()
{
// Move this object
myTrans.Translate (0, 0, objectSpeed*Time.deltaTime);
// Move the light to transform's position + offset.
// Note that the light's rotation has already been set and does
// not need to be re-set each frame.
lightTrans.position = myTrans.position + offset;
}

Resources