So I was trying to create a platformer game using HaxeFlixel, but I ran into a problem: after a FlxSprite object's x value passes 648, FlxG.collide doesn't seem to work at all. Here is a gif of the problem. As you can see, it works fine when the player's x is < 648, but when it becomes greater the FlxG.collision stops working.
The level is made of objects of the class Wall which extends FlxSprite with the only difference being that it's constructor loads the wall graphic and sets its immovable property to true. FlxG.collide is being called with player as the first argument and a FlxGroup (containing the walls) as the second argument. I'm not sure that it matters but the FlxState's super.update is being called before FlxG.collide.
Okay so I took a look at the HaxeFlixel source code (specifically the FlxG.overlap private function (line 363)), and I found that it only checks for objects inside the worldBounds FlxRect. After I knew that, all I had to do was set the bounds of that rect, which can be done with FlxG.worldBounds.set(?X:Float = 0, ?Y:Float = 0, ?Width:Float = 0, ?Height:Float = 0).
Related
I am perplexed about the SizeToContent method of the CMFCMenuButton control.
This is my dialog in the IDE:
As you can see, I have specifically made the button wider than the two on the far right.
I added the following code to OnInitDialog:
// Resize (if required)
const auto sizNewButton = m_btnReset.SizeToContent(true);
CRect rctButton;
m_btnReset.GetWindowRect(&rctButton);
if(sizNewButton.cx > rctButton.Width())
{
m_btnReset.SizeToContent();
}
Yet, when I run my application in English:
It has made it smaller. My application supports 50+ languages by using satellite DLLs and I was hoping to only resize to content if it was required. But it seems to resize it anyway. Have I missed a step here?
I have checked the properties for the control in the IDE and it is not set to auto resize:
I notice that the help documentation states:
The new size of the button is calculated to fit the button text, image, and arrow. The framework also adds in predefined margins of 10 pixels for the horizontal edge and 5 pixels for the vertical edge.
I had a look at my button:
Default size: 48 x 23 (the GeWindowRect result).
Calculated size: 57 x 23 (the SizeToContent result).
If I adjusted my code like this:
if((sizNewButton.cx - 10) > rctButton.Width())
That would bring it down to 47 and thus would not resize. I am assuming the code is not working right because of the padded margin that GetWindowRect knows nothing about.
Searched it, and found that the problem is MFC's CMFCMenuButton::SizeToContent() implementation in afxmenubutton.cpp:
CSize CMFCMenuButton::SizeToContent(BOOL bCalcOnly)
{
CSize size = CMFCButton::SizeToContent(FALSE); // <==== The culprit!!!
size.cx += CMenuImages::Size().cx;
if (!bCalcOnly)
{
SetWindowPos(NULL, -1, -1, size.cx, size.cy, SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOZORDER);
}
return size;
}
That is, it calls the base implementation of SizeToContent() with the bCalcOnly parameter set to FALSE, which means it will also resize the control to just fit the text (without the drop-down arrow). This is less than required for the text plus the arrow, and of course the original size is lost.
A workaround can be get the (original) width, before the SizeToContent() call, and work with this instead of the new one:
CRect rctButton;
m_btnReset.GetWindowRect(&rctButton);
const auto nOrigWidth = rctButton.Width(); // Store the original width
const auto sizNewButton = m_btnReset.SizeToContent(true); // This resizes the control!!!
if (sizNewButton.cx > nOrigWidth) // Compare to the original width rather than the new one
m_btnReset.SizeToContent();
else // Restore original width
m_btnReset.SetWindowPos(NULL, -1, -1, nOrigWidth, sizNewButton.cy, SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOZORDER);
Alternative Workaround:
Define a new CMFCMenuButton-based class, overriding SizeToContent() - in the implementation call the base CMFCButton::SizeToContent() with the bCalcOnly parameter passed by the caller, not with FALSE. Map the control to this class instead of CMFCMenuButton. That is use a class that fixes it. Too much of an overkill for just a workaround though.
Using revit-python-wrapper to create Wall then adjust the Wall height and Wall offset to the ground.
Here is the code
from rpw import db
from rpw import DB
start_point = XYZ(0, 0, 0)
end_point = XYZ(45, 0, 0)
# Wrapper Line
line = Line.new(start_point, end_point)
levels = db.Collector(of_class='Level')
level_0 = levels.get_first()
wall = DB.Wall.Create(doc, line.unwrap(), level_0.Id, False)
w = db.Wall(wall)
w.parameters['Unconnected Height'].value = 2675
w.parameters['Base Offset'].value = 45
Wall created successfully in the empty Revit project.
Using snoop revit DB, only one wall is found. The ID is : 318835
Checked the parameters belonging to this Wall - 318835. The parameter 'Unconnected Height' has correct double value: 2675.0 and the parameter "Base Offset" has correct double value: 45.0.
So far, everthing is perfect and per my expectation.
But, from the UI interface, the only Wall created is shown in wrong position. In 3D view, it's above the Level 1 which height is 4000.
And from the proporty tab of the selected Wall, the two parameters are also in the wrong values.
'Unconnected Height' has correct double value: 815340.0 and the parameter "Base Offset" has correct double value: 13716.0.
When I digged into deeper, I found actually the value I changed is shown in AsDouble. However, the value I changed in the UI is shown AsValueString. Both of them are pointing to the same property. However they are different, my understanding they should be the same value but in different data format.
Am I wrong?
I figured it out now.
Internally, Revit use feet rather than mm.
So, make sure convert the mm to feet then pass it to value.
w.parameters['Unconnected Height'].value = mm_to_feet(2675)
w.parameters['Base Offset'].value = mm_to_feet(45)
I have a collectionview I want to show just one cell at a time and based on my findings on SO it should be as simple as setting the item size to the size the collectionview itself but when I did that I see still a small bit of the next cell.
Here is how I've set up my collectionview:
cvCarousel.RegisterNibForCell(CarouselItemCollectionViewCell.Nib, CarouselItemCollectionViewCell.Key);
cvCarousel.CollectionViewLayout = new UICollectionViewFlowLayout
{
ItemSize = new CGSize(cvCarousel.Frame.Width, cvCarousel.Frame.Height),
MinimumInteritemSpacing = 0,
MinimumLineSpacing = 0,
ScrollDirection = UICollectionViewScrollDirection.Horizontal
};
I'm sure there's something simple I'm missing here but not sure what it is.
I guess you're calling the following code in viewDidLoad method.
Everything will have whatever frame size and position after a while until the layout has been performed, however it is too early in viewDidLoad method , we can only get the correct frame in viewDidLayoutSubviews method.
However , here you can directly replace cvCarousel.Frame with UIScreen.MainScreen.Bounds , because you just need a full screen item.
Refer to
https://developer.apple.com/forums/thread/52578
I'm trying to make my game more dynamic by making attack hitboxes scaleable. However when adding a new shape to the current CollisionShape it shows the correct radius when printing but the radius ingame is not corresponding to the new value.
The code I currently use is this:
var shape = CylinderShape.new()
shape.set_radius(new_radius)
shape.set_height(new_height)
$Spatial/CollisionShape.shape = shape
When running this I tried to print the current CollisionShape.shape.radius and it showed the new number however ingame the collisionshape is still the old shape and nothing changed (both visually with the debug option on and when testing the collision size)
So my question is: how do I change the shape or size of the shape in runtime.
Things I've already tried:
$Spatial/CollisionShape.shape.radius = new_radius
$Spatial/CollisionShape.shape.height = new_height
This gave the same result unfortunately. I've also tried to make the shape null before putting the new shape in the CollisionShape. This changed nothing aswell.
Am I missing something?
It looks like it's not possible to update a collisioon shape; you have to create a new one. I solved it like this, where I have a CSGBox which owns a StaticBody which owns a CollisionShape, and I want to make the static body's collision shape match the CSGBox:
var box : BoxShape = BoxShape.new()
box.extents.x = self.width/2
box.extents.y = self.height/2
box.extents.z = self.depth/2
$StaticBody/CollisionShape.shape = box
(This script is attached to the CSGBox).
I do not know how to set the position of a instance in gd script. The instanced shows up on the corner of the screen.
Thanks :)
It depends on what type of instance. If it's an object that has been derived from something like a Node2D, then position.x or position.y should do it. Do you have any code we can look at?
Depends on whether you want 2D or 3D.
A common method is as such:
Create the object you want to instance in its own scene.
Save the object as a scene (.tscn file) - for example "Scene1.tscn"
Call upon your instanced scene from your main scene as follows:
Make sure to preload the scene you plan to instance before your ready() function. For example if was called "Scene1", then declare :
onready var Scene1 = preload("res://Scene1.tscn")
Then, later in your code when you want to call an instance of the scene, do it as such:
var InstancedScene = Scene1.instance()
add_child(InstancedScene)
// This simply instances the scene (I think at co-ordinates (0,0,0)), but you can tell it where to instance it using the following example:
For 3D use:
InstancedScene.transform.origin = Vector3(50.0, 0.0, -50.0)
//Gives position x=50, y=0, x=-50.
This can also be used for rotation, just specify transform.basis and give a similar Vector3 coordinate set.
OR for 2D use:
InstancedScene.position = Vector2(100.0, 100.0)
//This instances the object 100 pixels across and 100 pixels down. Sub in whatever values you need. You can also specify a rotation using InstancedScene.rotation_degrees = 45 (To give 45 degrees for example)