Creating new objects with Game Maker GML - game-maker

I'd like to know if there's a way to check if an object exists on a point, and if not, create a new one while snapping the new object to a grid? I know you can use this instance_create(x,y,obj_to_create); but that just places on a point no matter what and doesn't snap to a grid. Also, is there a global mouse click event in Game Maker?
Thanks!

well there are a few (almost similar) functions that allow you to do this... But most straight forward is to use position_meeting(x,y, obj)
so the could would become:
if (!position_meeting(x, y, obj_to_create)) {
instance_create(x,y,obj_to_create);
}
Now to snap to grid you'll have to create it at a snapped position:
instance_create(x div GRIDW, y div GRIDH, obj_to_create);

Related

Aframe “come here” component. Such that the 2nd entity can find the 1rst entity and animate to it no matter where the user puts the 1st entity

How can I create a “come here” component. Such that the 2nd entity can find the 1rst entity and animate to it no matter where the user puts the 1st entity.
I have a button that travels with the user, it’s there when called, it doesn’t move with the camera, it vanishes before teleport and the idea of what I want to add to this is a function where when the user clicks this button (entity ID:One) it will say “come here” to another entity (Entity ID:Two) entity two is listening for entity one to be clicked, and then entity receives entity one’s coordinates, and then entity two travels to entity one.
A longer description of what I am trying to do: Previously I wrote: “How would I write a "come to me" function where one entity calls another to its new location. Lets say that I have a draggable entity, super hands is enabled and the user drags a cube to a new location. Okay so then the user clicks on the cube and a sphere flies to the cube's position but its z (position coordinate z), relative the cube is -1. Then the user drags the cube to another new location, clicks the cube with their laser, and the same sphere from before flies to the cube's new location but its still z -1 relative to the cube. How should I write that? what are the possible approaches? whats the efficient way to do it in aframe? would I create an invisible
child entity on the cube that has a -1 z position? is there a way to look up the global position of a child entity and then tell the sphere entity to update its position to match the child entities position? I would summarize this as a "come to me" function where one entity calls another to its new location.
What I tried: It was suggested that I look at two things 1. The pathfinding component in aframe extras that allows an npc to navigate a mesh during it’s animation, but for this example a simple animation is fine. 2. The follow component (which is 2 years old). The follow component is too abstract for my current level of understanding of aframe code. I don’t understand what it’s following or how to edit it to make it do what I want.
What else I tried: Then I stumbled upon “Interactive image grid in WebVR with A-frame” https://ottifox.com/prototype/2017/09/25/interactive-image-grid-in-webvr.html this makes a camera look up the location of an image, and then move to that image when clicked. Well I thought maybe I can replace the camera with a box and make the box move to another box instead of an image. Well I tried that, and so far it’s not doing anything.
My code is here at https://comehere.glitch.me https://glitch.com/edit/#!/comehere Can you help me solve how to have an entity look up the position of another entity and then animate to it the new location, so that the user can keep updating the position of the new entity, and when clicked the second entity can always move to anywhere the user wants it to move based on where the user puts the first entity.
You can manually move an entity towards a target, like i did here (press the sphere).
The idea is simple:
1) get the target position in a local space
targetPos = someEl.object3D.worldToLocal(target.object3D.position.clone())
2) move one entity towards another
someEl.object3D.translateOnAxis(targetPos, someDistance)
3) repeat until the object is close enough
var distanceFromTarget = currentPosition.distanceTo(target.object3D.position);
if (distanceFromTarget > 1) {
someEl.object3D.translateOnAxis(targetPos, distance);
}
You can throw it into an aframe component:
AFRAME.registerComponent('foo', {
init: function() {
this.target = document.querySelector("#target")
},
tick: function(t, dt) {
var currentPosition = this.el.object3D.position;
var distanceToTarget = currentPosition.distanceTo(target.object3D.position);
if (distanceToTarget < 1) return;
var targetPos = this.el.object3D.worldToLocal(target.object3D.position.clone())
var distance = dt*this.data.speed / 4000;
this.el.object3D.translateOnAxis(targetPos, distance);
}
}
and use it like this:
<a-box foo></a-box>
<a-box id="target"></a-box>
You can use the animation component like you did, by re-setting the to attribute:
// on some event:
this.el.setAttribute("animation", "to", newTargetPosition)
this.el.emit("startAnimation")
But it gets complicated if the target is moving since not only you would need to get the new position, but also the starting (from) position as well.

JavaFX - How to add array of MeshViews to group or scene

Update: I updated my code to loop through the list of meshviews and add each to the group using group.getChildren.add(meshview[i]) but still does not show up on screen. Thanks.
I am trying to add an array list of MeshView type to a scene in JavaFx based GUI. I was able to get an initial example to work where it was one MeshView, but now I have a case where the data that is read in from a file results in an array of MeshView type. I could not find a "add" or "addAll" type function on the Group type to let me loop through all of the elements and add them and I could not get the Group constructor to let me add the list at ones in the arguments. I am using a Group to contain them because the over all GUI makes use of a BorderLayout defined using an FXML file. So my initial version adds the meshview to a group along with some point lights and then that group is added to the center of the border layout using the set method of it. Any help would be appreciated. Thanks.
Ps. I think I may have just found an answer. I forgot the add method is under the get children:
group.getChildren().addAll(meshView, pointLight);
as the line above from another answer shows. But I would still be interested in hearing the best ways because I still am confused on how to deal with sitaution where you have say 20 meshviews that make up a part to be shown on screen and you want to combine those and appropriate lights etc and scale to fit in center or borderlayout. I'm guessin I can first all all meshviews using add and then add the lights but was not sure. Thanks again.
You can always add mesh views to any Node type object like Group or BorderLayout ex.
root.getChildren().add(meshView);
you can add as most as you can to this root object and translate the meshView in the scene
meshView.setTranslateX(200);
meshView.setTranslateY(200);
meshView.setTranslateZ(200);
and set the camera and lightpoints configuration and add them as well to the scene

how to make sprites stick together in game maker?

I don't know how to get sprites to stick to each other so they become one big object instead of tiny little pieces, for example:
attaching a thruster to a box, then the thruster stays in that spot while pushing the box, and also is there a certain term for what I'm talking about?
You could also attach all parts to one of the objects, it would sort of look like:
//Main object
x = 5;
y = 20;
//other object step event
x = obj_main.x + <any value to put it where you want>;
y = obj_main.y + <any value to put it where you want>;
//This will force the parts to follow the main object.
`
`
You can use an array, defined in the 'main' object to use a sort of grid to define where each piece is and then either draw each individual sprite, based on its position in the array, originating from the 'main' object's coordinates. Or just create an individual instance of an object if you would like to have additional functionality by trading off some performance.
For more information on arrays and how to position sprites and objects based on set coordinates, check out the GML documentation provided below:
Arrays:
https://docs.yoyogames.com/source/dadiospice/002_reference/001_gml%20language%20overview/401_06_arrays.html
lengthdir:
https://docs.yoyogames.com/source/dadiospice/002_reference/maths/real%20valued%20functions/lengthdir_x.html
what I did was make the object disabled, so when I press left and right it doesn't go anywhere, only the other piece would move, but when it came into contact it allowed the other piece to move along with it, and set its speed to the corresponding objects speed, in simpler term, when I collide with it, it turns the movement on and goes in the same direction as the current object in the same speed, making it look like its sticking

Conceptual question: Loose Coupling

I am building a graphic board like project where i am facing a design issue.
Main Class is Board which is a canvas responsible for handling mouse events when drawing shapes. It also has context variables such as currentShape or snapFlag to activate grid magnetism.
To handle the moving / resizing / rotating of the shapes, they inherit from a third party open source tool called ObjectHandles (flex).
I have a baseShape extending ObjectHandles main class to override some of its internal functions, like the onMove function.
When creating a shape (mouse down, move, mouse up) this is handle by the Board and it knows about his own snap flag.
var mouseUpPoint:Point = boardCanvas.globalToLocal(new Point(event.stageX, event.stageY));
var snapMouseUpPoint = snapPoint(mouseUpPoint.x, mouseUpPoint.y);
In my overidden onMove method i would like the shape to be aware of the Board snap flag and when its changing. How do i do this ?
Do i pass the Board as a parameter in my basicShape constructor so that i can check snap ?
Do i pass the flag as a parameter and somehow make all shapes listen for change ?
What is the cleanest solution ?
Thanks a lot.
I would approach this from a slightly different angle. I assume that the Board object traps mouse events first, so that it can decide which shape has been clicked on. I would have the board trap mouse movements as well, passing the correct (snapped or unsnapped) coordinates "down" to the selected Shape object, rather than letting the shape object figure it out.
This leaves the grid snap handling to the Board, and keeps your Shape object onMove method free of clutter.
Not knowing your app:
Is it ever possible for a Shape to have it's own 'snap' behavior? That is, could a Shape be excluded from snapping while others aren't? If so, make snapFlag a member of Shape. When snapFlag is set on the Board, iterate through your Shapes and set or don't set according to your rules.
If snapping behavior applies to all Shapes on the Board, consider an event-driven model (if it's available - I'm a Flex noob). When a Shape moves, have it raise an OnMove event. The Board can then respond and decide to 'snap' the Shape into place if it's appropriate.
If snap behavior applies to all Shapes and events aren't available, I'd just say the hell with loose coupling in this case - make the Shapes Board-aware. It sounds like you're saving a bunch of code by using the ObjectHandle. That benefit may out-weigh the cost of coupling your UI elements.
Just trying to think together with you..
I see no big deal in Shapes having IBoard interface.
Though, I don't like the idea that they have to check the flag on the board...
How would you pass the flag as parameter? In OnMove() method? didn't understood this quite well...could you expand?
Though..
If you try to think a bit about SRP - single responsibility principle...what is the responsibility of Shape classes?
Yea, this is what eJames wrote already.
It feels to me that their main responsibility is probably NOT handling mouse events...here need to know more about your application, but my general feeling is why not someone else get this mouse down and then figure out what the shape should do with it and for instance call Draw() on the Shape with new coordinates?
Let's say you want to apply something like Composite pattern (Shapes inside shapes...) and you want them to be able to handle those mouse events themselves...but then
Then it would be logical if they perceived this mouse event in their local coordinates, but then I think you should provide all the information through this event (local coordinates, mouse status...) so that they don't have to ask for "global" variables on the board...
Passing the flag as a parameter for the shape constructor. But it wont be good since flag is going to change and i have to make each shape to update their flag copy on change.
Its true that shape responsibility is not to know how to handle mouse events. But thats what ObjectHandles do: react to events, update height width rotation parameter of the shape.
Maybe i should transfer some of the library code in my board class to handle shape selection and movement / resizing / rotation.
OnMouseMove ObjectHandles
protected function onMouseMove(event:MouseEvent) : void
{
if( ! visible ) { return; }
if( ! event.buttonDown )
{
setMouseCursor( event.stageX, event.stageY );
return;
}
if(parent == null )
{
return;
}
var dest:Point = parent.globalToLocal( new Point(event.stageX, event.stageY) );
var desiredPos:Point = new Point();
var desiredSize:Point = new Point();
var desiredRotation:Number = 0;
... plenty more
then
if( wasMoved ) { dispatchMoving() ; }
if( wasResized ) { dispatchResizing() ; }
if( wasRotated ) { dispatchRotating(); }
So i can not listen for move event and tell the board to snap it since the shape is already moving freely. I should add snap here:
var dest:Point = parent.globalToLocal( new Point(event.stageX, event.stageY) );
All shapes follow the snap rule there can not be one snapping and the other free.
Solved it this way:
Since i overridde onMouseMove in my baseShape class and i am using PureMVC framework, i just made baseShape aware of my boardMediator.
override protected function onMouseMove(event:MouseEvent) : void
{
[...]
// added on override
var board:BoardMediator = ApplicationFacade.getInstance().retrieveMediator(BoardMediator.NAME) as BoardMediator;
Then
desiredPos = board.snapPoint(desiredPos.x, desiredPos.y);
Maybe not super pretty but it works, o
Overridding the globalToLocal method in my board view did work too but some more calculations were done inside onMouseMove resulting in an out of alignment snap move.
Use ObjectHandles Version 2, and then create a constraint to do what you want.

Flex - Is there a way to specify what direction a ComboBox will open?

Maybe I should further qualify this - Is there a way to specify which direction a ComboBox will open without copying and pasting the entire ComboBox class and ripping out the code where it determines which direction it will open in...
I'm my specific case - I need it to open upwards - always.
UPDATE: You can't fix this by subclassing it because the function that handles the direction of the opening is:
private function displayDropdown(show:Boolean, trigger:Event = null):void
And that bad boy uses a fair amount of private variables which my subclass wouldn't have access to...
If you build up the Menu object yourself, you can place the menu anywhere you want by simply setting the x,y coordinates of the menu object. You'll need to calculate those coordinates, but you might be able to do this easily without subclassing ComboBox.
I am doing something similar with PopUpButton; you might find it easier to work with PopUpButton. This is based on real code from my current project:
private function initMenu(): void {
var m:Menu = new Menu();
m.dataProvider = theMenuData;
m.addEventListener(MenuEvent.ITEM_CLICK, menuClick);
m.showRoot = false;
// m.x = ... <-- probably don't need to tweak this.
// m.y = ... <-- this is really the interesting one :-)
theMenu.popUp = m;
}
<mx:PopUpButton id="theMenu" creationComplete="initMenu()" ... />
BTW, to get the PopUpButton to act more like I wanted it (always popup, no matter where the click), setting openAlways=true in the MXML works like a charm.
I doubt it - you'd need to subclass the control (which isn't that big a deal.)
Maybe you could mess with the real estate so it's placed in such a fashion (e.g. crowded into the lower right corner) that up is naturally coerced?
I would recommend checking out this post. Yes, you do have to grab the ComboBox code and modify it, but at least now you have an idea where the modifications need to go.
You could set the MaxDropDownHeight, if you set it big enough Windows will automatically set the direction upwards.
This irritated me no end. I have uploaded a solution, its a simple Class that extends the PopUpButton and removes the logic of stage bounds detection as it failed 50% of the time anyway. My code just allows you to simply specify whether you want to open the menu up or down:
http://gist.github.com/505255

Resources