I created a new path2d following the instructions in the my first game article: http://docs.godotengine.org/en/3.0/getting_started/step_by_step/your_first_game.html
I wanted to move the "box" on screen so that I could see how the mobs spawn in, but when I ran the scene, it stayed off screen.
I created a new path2d, centered this one in the middle of the screen, and it works like I wanted it to, but now I moving this one in the editor doesn't update the position in game.
What's going on?
Thanks
func _on_mobtimer_timeout():
$mobtimer.wait_time = 0.1 + randf() / 2
$mobspawn/moblocation.set_offset(randi())
var mob = Mob.instance()
add_child(mob)
var direction = $mobspawn/moblocation.rotation + PI/2
mob.position = $mobspawn/moblocation.position
direction += rand_range(-PI/8, PI/8)
mob.rotation = direction
mob.set_linear_velocity(Vector2(rand_range(200, 200 + score * 30), 0).rotated(direction))
A Node2D's position property is relative to it's parent's position. The code from the Dodge The Creeps tutorial assumes that MobPath is located at 0, 0 and fails when that assumption is false.
In your case you are taking a MobSpawnLocation's position relative to MobPath and then setting it as the new Mob's global position.
Luckily Node2D's have another property that we can use in these circumstances global_position. It can be used like this:
mob.position = $mobspawn/moblocation.global_position
http://docs.godotengine.org/en/stable/classes/class_node2d.html#member-variables
This isn't a full solution, but I found a weird workaround. Instead of changing the position in the editor, if you use the nodes on the orange box (at the intersection of orange and blue), you can kind of alternate to move the box around.
Related
I am trying to get my rock.png to move to the side(+x axis) when my mouse is moving. You can see that _target is the position of the event and the event is the mouse moving.
I then got the node image and set it to a variable.
In the else statement I made the rock.position the position of the _target and gave it somee space away from the _target
I want this to move because my camera moves and I want it to move with the flow of the camera
``
extends Camera2D
const zone = 10
onready var rock = get_node("rocks_png_1")
func _input(event: InputEvent) -> void:
if event is InputEventMouseMotion:
var _target = event.position
if _target.length() < zone:
self.position = Vector2(640,350)
else:
self.position = _target.normalized() * (_target.length() - zone) * 0.5
rock.position = Vector2(int(_target)+40, int(_target)+20)
``
From the code I used above I get this error
Invalid get Index 'position' (on base: 'TextureRact')
I tried just using the same code as I used in my self.position for the camera that made it move, but when I try it for the rock.position it gives me an error that tells me I need a Vector?
Invalid get Index 'position' (on base: 'TextureRact')
The error is telling you that TextureRect does not have a position property.
What happens is that a TextureRect is a Control which are positioned differently from Node2D (Camera2D is a Node2D). You can try using rect_position with it. Although I think you would be better off using a Sprite instead of a TextureRect (Sprite is a Node2D).
Notice that your TextureRect is a child of the Camera2D in the scene tree. Well, a Node2D would move with its parent automatically. So changing it to Sprite would negate the need of the line of code you are using to move it.
… Actually, due to the way Camera2D works (it has drag and limits) you might still want do something (depending what your goal is). So, know that the get_camera_screen_center method will give you the actual visual center of the screen (which is not the target of the Camera2D, again due to drag and limits).
I can't seem to get a QGraphicsEllipseItem to show up in my view. I am attempting to use it in combination with a QGraphicsLineItem:
# Instantiate the line object:
self.profileLine = QGraphicsLineItem()
self.profileLine.setPen(QPen(Qt.yellow, 1.0))
self.profileLine.setLine(self.StartX, self.StartY, self.StopX, self.StopY)
self.scene.addItem(self.profileLine)
# Instantiate the circle:
self.profileStopHandle = QGraphicsEllipseItem()
self.profileStopHandle.setPen(QPen(Qt.yellow, 1.0))
self.profileStopHandle.setRect(self.StopX, self.StopY, 50, 50)
self.scene.addItem(self.profileStopHandle)
Later, in my mouse move event, I determine the current mouse coordinates, assign them to StopX/StopY and redraw the line from the start point to the new stop point as well as draw the ellipse around the new stop point:
self.profileLine.setLine(self.StartX, self.StartY, self.StopX, self.StopY)
self.profileStopHandle.setPos(self.StopX, self.StopY)
The line shows up fine and behaves just as it should, but no matter what I cannot seem to get the ellipse to draw. I know the point coordinates I'm passing to it are correct because they are the same ones I'm using for the line. The ellipse just never appears as if it was never created in the first place. What am I doing wrong here (it must be something very basic)? Thank you in advance.
The issue was the Z-value (amateur mistake). I brought the ellipse to the foreground and now it is visible:
self.profileStopHandle.setZValue(self.sceneImage.zValue() + 1.0)
How would I go about changing the registration point of a movieclip labeled "tablet" placed on the stage (root) dynamically?
For example: I have the following:
var tablet = this.tablet; //movieclip labeled "tablet" on stage
function resetTablet(){
tablet.regX = tablet.width/2; //move registration point to center
tablet.regY = tablet.height/2;
}
However when I call it using GSAP:
var tl = new TimelineLite();
tl.to(tablet, 1, {alpha:1, onComplete:resetTablet})
.to(tablet, 3, {alpha:0, scaleX:1.5, scaleY:1.5})
the registration point is still set to the upper left corner rather than the center.
What am I doing wrong here? Thanks!
Registration points affect change both the transformation point, but also the position. If you set a displayobject that is 100x100 pixels to regX=50;regY=50, then it will draw from that point, moving the content 50px to the top and left. If you make that change you should also translate the clip to x=50;y=50.
An issue with you example is that there is no width or height on EaselJS content (explained here). You can get the bounds of anything generated by Flash CC using the nominalBounds property, which Flash exports as a property on every object. If you have multiple frames, you can turn on "multi-frame bounds" in the publish settings, and a frameBounds property is added to the objects as well.
Note that nominalBounds and frameBounds are not used by the getBounds method.
Here is how you might be able to approach it.
var bounds = tablet.nominalBounds;
tablet.regX = bounds.width/2;
tablet.regY = bounds.height/2;
// Optional if your actual registration point was [0,0] before:
tablet.x += tablet.regX;
tablet.y += tablet.regX;
Hope that helps.
There is a too long, didn't read version down below.
So I've been making a little game in which the player has to click on a grid of bricks that matches the color of the needed brick in the upper right hand corner of the screen. After they click on the needed color, the bricks explode and the bricks of the same color next to them explode as well creating combos. That leaves holes in the grid so I have to somehow reset the grid itself without resetting the gamestate itself. I've got something working right now which is this:
private function ResetNow():Void
{
if (Restter == 1) Restter = 0;
//if this block is up here, same results
/*
wantedBricks.kill();
wantedBrik._changeColor = FlxMath.rand(0, 2);
bricks.autoReviveMembers = true;
bricks.revive();
*/
Restter = 0;
//Removes stray detectors so the neverending combo bug won't occur
for (stray in dets.members) stray.kill();
if (Restter == 0)
{
wantedBricks.kill();
wantedBrik._changeColor = FlxMath.rand(0, 2);
bricks.autoReviveMembers = true;
bricks.revive();
wantedBricks.autoReviveMembers = true;
wantedBricks.revive();
for (zgem in bricks.members) zgem.EQUITYCHECK = FlxMath.rand(0, 2);
}
//add(bricks);
Restter = 1;
}
So, again, I have a grid of blocks set up at create, that is group bricks. And I have a sprite in the upper right corner which is wantedBrik. What happens during gameplay, is the player clicks on the bricks that matches the wanted bricks to clear them out of the grid. When there are no more wantedBricks(a group), it is supposed to reset the grid, and change the color of the wantedBrik. I also have it somewhere else in the code that if a member of the big grid's EQUITYCHECK(basic object hacked in value) is equal to the wantedBrik, add it to the wantedBricks(which, is why I'm checking for no more of them). So, what happens?
Well, if the color of the wantedBrik doesn't change, everything's fine and resets like normal. the wantedBricks group acurately counts the bricks that actually match the wantedBrik's color. And when it does change, for some reason, gameplay is normal. BUT, wantedBricks not only thinks that the old color is still needed, but it also thinks the new color is still needed too. So when the player clicks the new needed color bricks, they do explode, but because wantedBrik thinks the old color is still wanted, it doesn't hit null and the grid won't reset.
What can I do to make sure that wantedBricks behaves correctly after a color change?
TL;DR version: I need to get a Haxe array to forget or lose old numbers. How can I do this?
The "Pirate Pig" sample may be useful to you. Since it is a puzzle game, there may be some similar problems that were solved there. You can find it using openfl create or nme create depending on which you are currently using.
You can create a simple array like this:
var myArray = [];
You can also type arrays, like this:
var numbers = new Array<Float>();
Then you can use push(), concat() and other array methods.
It seems like given the information in stroke_extents() and the translate(x, y) and scale(x, y) functions, I should be able to take any arbitrary cairo (I'm using pycairo) path and "best fit" it. In other words, center it and expand it to fill the available space.
Before drawing the path, I have scaled the canvas such that the origin is the lower left corner, up is y+, right is x+, and the height and width are both 1. Given these conditions, this code seems to correctly scale the path:
# cr is the canvas
extents = cr.stroke_extents()
x_size = abs(extents[0]) + abs(extents[2])
y_size = abs(extents[1]) + abs(extents[3])
cr.scale(1.0 / x_size, 1.0 / y_size)
I cannot for the life of me figure out the translating though. Is there a simpler approach? How can I "best fit" a cairo path on its canvas?
Please ask for clarification if anything is unclear in this question.
I have found a solution that I like (at least for my purposes). Just create a new surface and paint the old surface on to the new one.
As for the scale only, I have done a similar thing to adjust an image inside a box with a "best-fit" approach. As about scale, here is the code:
available_width = 800
available_height = 600
path_width = 500
figure_height = 700
# formulas
width_ratio = float(available_width)/path_width
height_ratio = float(available_height)/figure_height
scale = min(height_ratio, width_ratio)
# result
new_path_width = path_width*scale
new_figure_height = figure_height*scale
print new_path_width, new_figure_height
The image gets drawn aligned to the origin (top left in my case), so perhaps a similar thing should be done to translate the path.
Also, this best fit is intended to preserve aspect ratio. If you want to stretch the figure, use each of the ratios instead of the 'scale' variable.
Hope I have helped