2D Collision problems - 2d

I have the following code:
function collisionDetect(left1,right1,top1,bottom1,left2,right2,top2,bottom2,dir)
local left,right,top,bottom=false,false,false,false
if left1<right2 then left=true end
if right1>left2 then right=true end
if top1>bottom2 then top=true end
if bottom1<top2 then bottom=true end
if dir.x>0 and (top or bottom) then
if right then return 1 end
elseif dir.x<0 and (top or bottom) then
if left then return 2 end
elseif dir.y>0 and (left or right) then
if bottom then return 3 end
elseif dir.y<0 and (left or right) then
if top then return 4 end
end
return 0
end
left1, right1, etc. are arguments containing the position of the respective bounding box (box 1 or 2).
dir is a "Vector2" (contains an x and y property).
For some reason, my code is returning collisions for objects no where near by. Any ideas?
EDIT:
I have solved my problem, here is the code for anybody googling the subject.
(It's in Lua, a pretty straight forward and simple to interpret language)
function collisionDetect(left1,right1,top1,bottom1,left2,right2,top2,bottom2,dir)
local insideHorizontal=false
local insideVertical=false
if left1<right2 then insideHorizontal=true end
if right1>left2 then insideHorizontal=true end
if top1>bottom2 then insideVertical=true end
if bottom1<top2 then insideVertical=true end
if insideHorizontal and insideVertical then
return true
end
return false
end

Have a look at this for a nice collision detection tutorial/algorithm.
Essentially:
bool check_collision( SDL_Rect A, SDL_Rect B )
{
//...
//Work out sides
//...
//If any of the sides from A are outside of B
if( bottomA <= topB )
{
return false;
}
if( topA >= bottomB )
{
return false;
}
if( rightA <= leftB )
{
return false;
}
if( leftA >= rightB )
{
return false;
}
//If none of the sides from A are outside B
return true;
}
Or, in terms of your code:
function collisionDetect(left1,right1,top1,bottom1,left2,right2,top2,bottom2,dir)
if bottom1<=top2 then return true end
if top1>=bottom2 then return true end
if right1<=left2 then return true end
if left1<=right2 then return true end
return false
end
(this isn't a language I know, so I'm guessing a bit)

Related

How to query exactly selected items in Paper.js?

According to my understanding, project.getItems({selected: true}) returns wrong results: I'm selecting a curve, it returns the parent Path: Sketch
Try clicking on a curve or a segment. Whole path will be moved. Then try changing the behavior by setting var workaround = false to var workaround = true to observe desired behavior.
How can I get exactly what is really selected?
Current workaround
I'm currently adding those objects into an array on selection and use those items instead of project.getItems({selected: true}).
The thing is that in Paper.js architecture, curves and segments are not items (they are part of a specific item which is the path). So you shouldn't expect project.getItems() to return anything else than items.
Another thing you have to know is that a path is assumed selected if any of its part is selected (curves, segments, points, handles, position, bounds, ...). And a curve is assumed selected if all of its parts are selected (points and handles).
With that in mind, you can create an algorithm to retrieve "what is really selected" based on project.getItems({selected: true}) as its first part. Then, you need to loop through curves and segments to check if they are selected.
Here is a sketch demonstrating a possible solution.
var vector = new Point(10, 10);
// Create path.
var path = new Path({
segments: [
[100, 100],
[200, 100],
[260, 170],
[360, 170],
[420, 250]
],
strokeColor: 'red',
strokeWidth: 10
});
// Translate given thing along global vector.
function translateThing(thing) {
switch (thing.getClassName()) {
case 'Path':
thing.position += vector;
break;
case 'Curve':
thing.segment1.point += vector;
thing.segment2.point += vector;
break;
case 'Segment':
thing.point += vector;
break;
}
}
// On mouse down...
function onMouseDown(event) {
// ...only select what was clicked.
path.selected = false;
hit = paper.project.hitTest(event.point);
if (hit && hit.location) {
hit.location.curve.selected = true;
}
else if (hit && hit.segment) {
hit.segment.selected = true;
}
// We check all items for demo purpose.
// Move all selected things.
// First get selected items in active layer...
project.activeLayer.getItems({ selected: true })
// ...then map them to what is really selected...
.map(getSelectedThing)
// ...then translate them.
.forEach(translateThing);
}
// This method returns what is really selected in a given item.
// Here we assume that only one thing can be selected at the same time.
// Returned thing can be either a Curve, a Segment or an Item.
function getSelectedThing(item) {
// Only check curves and segments if item is a path.
if (item.getClassName() === 'Path') {
// Check curves.
for (var i = 0, l = item.curves.length; i < l; i++) {
if (item.curves[i].selected) {
return item.curves[i];
}
}
// Check segments.
for (var i = 0, l = item.segments.length; i < l; i++) {
if (item.segments[i].selected) {
return item.segments[i];
}
}
}
// return item by default.
return item;
}
That said, depending on your real use case, your current workaround could be more appropriate than this approach.

shortcode to insert text depending on day of week

I would like to create a shortcode of [time] that would display 6:00-7:00AM everyday except for Saturday or Sunday, as those two days would display the time 8:00-9:00AM. How would I do this?
This is what I have come up with...
// [time]
function displaytime(){
if (date('l') == 'Saturday' || date('l') == 'Sunday')){
echo '8:00-9:00AM';
}else{ //it's a weekday
echo '6:00-7:00AM';
}
}
add_shortcode('time', 'displaytime');
// end display time
What it currently looks like... (next to Sat and Sun it should display 8:00-9;00AM)
I have 7 shortcodes to display the next 7 days of the week. So perhaps this is what is causing it to not work correctly?
// [tomorrow]
function displaydate_tomorrow(){
return date('D, M j.', strtotime('+1 day'));
}
add_shortcode('tomorrow', 'displaydate_tomorrow');
// end tomorrows date
// [tomorrow2]
function displaydate_tomorrow2(){
return date('D, M j.', strtotime('+2 day'));
}
add_shortcode('tomorrow2', 'displaydate_tomorrow2');
// end tomorrows date2
// [tomorrow3]
function displaydate_tomorrow3(){
return date('D, M j.', strtotime('+3 day'));
}
add_shortcode('tomorrow3', 'displaydate_tomorrow3');
// end tomorrows date3
// [tomorrow4]
function displaydate_tomorrow4(){
return date('D, M j.', strtotime('+4 day'));
}
add_shortcode('tomorrow4', 'displaydate_tomorrow4');
// end tomorrows date4
// [tomorrow5]
function displaydate_tomorrow5(){
return date('D, M j.', strtotime('+5 day'));
}
add_shortcode('tomorrow5', 'displaydate_tomorrow5');
// end tomorrows date5
// [tomorrow6]
function displaydate_tomorrow6(){
return date('D, M j.', strtotime('+6 day'));
}
add_shortcode('tomorrow6', 'displaydate_tomorrow6');
// end tomorrows date6
// [tomorrow7]
function displaydate_tomorrow7(){
return date('D, M j.', strtotime('+7 day'));
}
add_shortcode('tomorrow7', 'displaydate_tomorrow7');
// end tomorrows date7
// [time]
function displaytime(){
if (date('D') == 'Saturday' || date('D') == 'Sunday'){
return '8:00-9:00AM';
}else{ //it's a weekday
return '6:00-7:00AM';
}
}
add_shortcode('time', 'displaytime');
// end display time
It's stated in the docs:
Note that the function called by the shortcode should never produce output of any kind. Shortcode functions should return the text that is to be used to replace the shortcode.
try with this, and don't hesitate to comment if there is any issue:
// [time]
function displaytime(){
if (date('l') == 'Saturday' || date('l') == 'Sunday'){
return '8:00-9:00AM';
}else{ //it's a weekday
return '6:00-7:00AM';
}
}
add_shortcode('time', 'displaytime');
// end display time
EDIT after question update: The reason it displays the same time for all 7 places is because your initial code tests date('l') which only consider current day, so it will display '6:00-7:00AM' everywhere if current day is not Saturday or Sunday, or else '8:00-9:00AM' everywhere. In addition to this, you are creating 8 different shortcodes when only 1 should be enough for the 7 days, and the last for the time should be merged too, or else it has no way of knowing which day we consider.
EDIT 2: added code to set the wordpress timezone setting for the function, then restore to its original setting that was before the function.
updated code with a single shortcode for all (now you learn to add attributes to a shortcode!):
// use examples: [nextdaytime day="+1 day"] [nextdaytime day="+2 day"]
function displaynextdaytime($atts){
$originalZone = date_default_timezone_get(); //save timezone
date_default_timezone_set(get_option('timezone_string')); //set it to your admin value
$time = strtotime($atts['day']); //time for the date() function based on our 'day' attribute
if (date('l', $time) == 'Saturday' || date('l', $time) == 'Sunday'){
$timeStr = '8:00-9:00AM';
}else{ //it's a weekday
$timeStr = '6:00-7:00AM';
}
$returnVal = date('D, M j.', $time) . ' ' . $timeStr;
date_default_timezone_set($originalZone) //restore original zone
return $returnVal;
}
add_shortcode('nextdaytime', 'displaynextdaytime');
// end display next day and time

Trouble with passing variable from one function to next?

I am trying to edit a plugin in wordpress that deals with a points system to suit my needs. I have two functions, A and B. Function A is basically telling the plugin to deal a different amount of points depending on a post term Id. Function B is now trying to incorporate the variable $amount from Function A to limit users from ever going into a negative balance. My problem is that I can't get Function B to get the $amount from Function A when determining its argument. I tried to set it as a global variable but it didn't work. Can someone suggest what would be the best approach for this?
In basic words, the plugin is set to always take 100 points from the user when
"dealing_points". However, if the post term_id is equal to any of the below, then the amount of points changes. Now I need the $amount in function B to always equal the new $amount that was calculated within the if condition when completing its argument.
function A( $run, $request ) {
if ( $run['ref'] == 'dealing_points' ) {
// Original amount (Usually take 100 points)
$amount = $request['amount'];
if(isset($_POST['term_id'])){
if ($_POST['term_id'] == '74' )
$amount = -50;
elseif ($_POST['term_id'] == '75' )
$amount = 50;
$run['amount'] = $amount;
}
}
return $run;
}
function B( $reply, $request) {
if ( $reply === false || $request['amount'] > 0 ) return $reply;
extract( $request );
$user_balance = get_users_balance( $user_id, $type );
// Don't allow user to ever go below zero
if ( ( $user_balance + $amount ) < 0 ) return null;
return $reply;
}

I thought this is already tail recursive. But if not how do I make it so?

Not the best title for the question, I agree. But I couldn't come up with something else. Sorry.
Writing a simple Singly Linked List code in Groovy, I want to add a method which takes in two lists and appends the right one to the left one. This is what I cam up with.
private static class Node {
Node next = null
def head
#TailRecursive
Node append(Node left = this, Node right) {
if (!right) return left
if (!left) return right
if (!left.next) left.next = right
else left.next = append(left.next, right)
return left
}
}
But I got the error,
LinkedList.groovy: 23: Recursive call could not be transformed by #TailRecursive. Maybe it's not a tail call.
# line 23, column 30.
else head.next = append(head.next, tail)
Is it because of the return statement in the end that it's not tail recursive? How do I fix this?
Based on the tip user2864740 gave, here's the tail recursive implementation. It should be as efficient as the non-tail-recursive one I posted in the question.
#TailRecursive
Node append(Node prevTail = this, Node tail = this?.next, Node right) {
if (!right) return left
if (!prevTail) return right
if (!tail) prevTail.next = right
else return append(tail, tail?.next, right)
}
Something like below would suffice?
import groovy.transform.TailRecursive
#TailRecursive
LinkedList mergeLinkedList(LinkedList left = [], LinkedList right = []) {
if ( !left ) {
right
} else if ( !right ) {
left
} else {
left.add( right.head() )
mergeLinkedList( left, right.tail() )
}
}
def left = (1..100) as LinkedList, right = (200..500) as LinkedList
assert mergeLinkedList( left, right ) == ((1..100) + (200..500)) as LinkedList

How to assign dataGrid to other dataGrid in Flex. a = b doesn't work

in Flex I have something like that:
var dg:DataGrid = new DataGrid();
if (something) dg = dg1 else if (something_2) dg = dg2;
dg.dataProvider.getItemAt(3).id;
and dg is ALWAYS pointing at DataGrid (even if dg1 has name DataGrid_test and dg2 = DataGrid_test2) and finally action is made on my first DataGrid (DataGrid_test).
Why?
How can I pass dg1 or dg2 to dg?
Here is pasted almost full code of this part of application. I edited it to make that more clear.
var dg:DataGrid = null;
if ( currentState == "state1" ) { //if this condition is true then app. go into if and
dg = dataGrid_first; // make dg = DataGrid (1)
test.text = "inco"; // shows "inco" in "test" label
} else if ( currentState == "state2" ) { // if this is true then app. go..
dg = dataGrid_second; //here and set dg as DataGrid (exactly!) (2)
test.text = "outgo"; // and change test label into blank text (earlier text disapears)
}
search(dg);
It is modified with advice of '#splash'
Still not working.
EDIT:
I made this sceond edit to answer for all You who are helping me with that :) I think that it will be the best way. In codeblock above I added comments. (please read now comments and after that come back here :) )
Now I will explain exactly what happens.
I debug it many times and here are results:
dg is pointing at DataGrid (as component in flex, not as my dataGrid_first), I needed to extend DataGrid so now it is ColorColumn component (I don't know if I called it properly), not DataGrid. And dg is pointing at ColorColumn not at dataGrid_first or dataGrid_second. I even tried today the same thing what suggest #splash:
if ( currentState == "state1" ) {
test.text = "inco";
search(dataGrid_first);
} else if ( currentState == "state2" ) {
test.text = "outgo";
search(dataGrid_second);
}
and search still points at ColorColumn :/ My problem is really easy- I just want to pass to search different dataGrid on each state. If You have other ideas how I can do that in right way then I will pleased to hear about it. :)
But still I don't understand why it doesn't work. My search function uses algorhitm Boyer-Moor for searching through dataGrid.dataProvider for some text. If it find something then it is pushed into new array and after passing whole dataProvider I colorize rows with searched word.
If dg is never pointing to dg1 and dg2 then your (something) expressions may be evaluate to false. Check the value of your if-conditions - this should be easy to debug.
This should work:
var dg:DataGrid = null;
if (something)
dg = dg1;
else if (something_2)
dg = dg2;
if (dg)
{
// do something with dg
}
[Update]
I still can't see why your code isn't working, but you could simplify it like this:
if ( currentState == "state1" ) {
test.text = "inco";
search(dataGrid_first);
} else if ( currentState == "state2" ) {
test.text = "outgo";
search(dataGrid_second);
}
I'd propose to write this - since I guess either dg1 or dg2 should be assigned:
if (something) {
dg = dg1;
} else {
dg = dg2;
}
There may be cases, where if () {} else () {} neither executes the first or the second conditional block.
Finally a small hint, which structurally eliminates unwanted assignments in if conditions: Always write the literal left of the comparison operation: if ( "state1" == currentState ). If you accidentally typed = instead of ==, the flex compiler emits an error. The other notation silently assigns a value.
Additionally: Did you single-stepped through your code and watched the variables dg1, dg2 and dg? If not, set a breakpoint a few line before the if-statement and run the code step by step from there on. What do you see?
Here's a another tip: Use assertions to check for inconistencies:
package my.company.utilities {
public function assert(expression:Boolean):void {
// probably conditionally compile this statement
if (!expression) {
throw new Error("Assertion failed!");
}
} // assert
}
Use it e.g. at the beginning of a method like this:
public function doTransaction( fromAccount:int, toAccount:int ) {
assert( 0 < fromAccount );
assert( 0 < toAccount );
}
A typically good use of assert is to check variables regarding their range. As of the above example, fromAccount and toAccount should always be positive. Due to a bug, bad values might get passed to doTransaction(). In this case, the assertion fires an error.

Resources