Godot duplicate and tween flicky - animation

I am using Godot v3.42-v3.45 to make an implemetation of the boardgame Citadel. In order to make a card move, I develop a tween system. But sometimes the original card node will be "queue_free()"ed immediately after the tween starts, and the card will be gone from the screen and I don't want to wait till it's finished. So I try to make a copy node for just animation, hide the original one, set the final values on the original node, run the tween, show the original node and hide the copied node. But it gets flicky, the copied node seems to blink when the tween is finished. I try a lot of measures but it still blinks. Could anybody help me? Please run the ani_flip_move() function.
extends Node2D
onready var TimerGlobal = get_node("/root/Main/Timer") # a global timer stick to the main scene
onready var Data = get_node("/root/Main/Data") # Data.XXX is just some constants, Data.FAR_AWAY = Vector2(99999, 99999)
onready var Signal = get_node("/root/Main/Signal") # a signal bus stick to the main scene
class Trans:
var motion_list: Array
var copies: Dictionary
func _init() -> void:
motion_list = []
copies = {}
func add(node: Node2D, prop_name: String, start_val, end_val, ani_time: float = 1) -> void:
var copy
if node in copies:
copy = copies[node]
else:
copy = node.duplicate(node.DUPLICATE_USE_INSTANCING)
copies[node] = copy
node.set(prop_name, end_val)
motion_list.append([node, copy, prop_name, start_val, end_val, ani_time])
class Interval:
var wait_time: float
func _init(times: float) -> void:
wait_time = times
func animate(action_list: Array) -> void:
var _useless
var tween = Tween.new()
add_child(tween)
for action in action_list:
if action is Trans:
for motion in action.motion_list:
var orgi_node = motion[0]
var copy_node = motion[1]
var prop_name = motion[2]
var start_val = motion[3]
var end_val = motion[4]
var ani_time = motion[5]
orgi_node.set(prop_name, end_val)
orgi_node.set_visible(false)
if not copy_node.is_inside_tree():
add_child(copy_node)
_useless = tween.interpolate_property(
copy_node,
prop_name,
start_val,
end_val,
ani_time,
Tween.TRANS_CUBIC,
Tween.EASE_IN_OUT
)
_useless = tween.start()
yield(tween, "tween_all_completed")
for motion in action.motion_list:
var orgi_node = motion[0]
var copy_node = motion[1]
if is_instance_valid(orgi_node):
orgi_node.set_visible(true)
orgi_node.set_z_index(0)
if is_instance_valid(copy_node):
copy_node.set_z_index(0)
copy_node.queue_free()
elif action is Interval:
TimerGlobal.set_wait_time(action.wait_time)
TimerGlobal.start()
yield(TimerGlobal, "timeout")
remove_child(tween)
tween.queue_free()
Signal.emit_signal("all_ani_completed")
func ani_flip_move(
obj: Node2D,
end_pos: Vector2 = Data.FAR_AWAY,
end_scale: Vector2 = Data.FAR_AWAY,
end_visible: bool = true,
end_face_up: bool = true,
ani_time: int = 1
) -> void:
if end_scale == Data.FAR_AWAY:
end_scale = obj.scale
if end_pos == Data.FAR_AWAY:
end_pos = obj.global_position
var a1 = Trans.new()
var z_index = obj.z_index
a1.add(obj, "global_position", obj.global_position, end_pos, ani_time)
a1.add(obj, "scale", obj.scale, end_scale, ani_time)
a1.add(obj, "z_index", 1, 1, ani_time)
if "face_up" in obj:
a1.add(obj, "face_up", obj.face_up, end_face_up, ani_time)
animate([a1])

Related

Assistance with loop inside a loop for a loan deduction schedule google apps

Our company offers soft loans to employees. I am trying to write some code that will set up a loan deduction schedule once a loan is approved. This is all done on google sheets. The schedule then can be linked to payroll etc.
The approved loans will appear in a format like this:-
Loans Approved - [Serial, Employee ID,Amount, Monthly Deductions,Requested Date,Deduction Start Date]
I am looking to build an array that will have the first 4 elements that repeat and the deduction month to increase by 1
So far this is my code
function myFunction() {
var ss = SpreadsheetApp.getActive();
var sheet = ss.getSheetByName("Loans");
var range = sheet.getDataRange();
var data = range.getValues()
var lastRow = range.getLastRow()
var scheduleSheet = ss.getSheetByName("Schedule")
var scheuduleLastRow = scheduleSheet.getDataRange().getLastRow;
for(let i=1;i<lastRow;i++){
var serial = data [i][0]
var id = data [i][1]
var amount = data[i][2]
var monthlyRepayment = data [i][3]
var startDate = new Date (data [i][5])
var markScheduleDone = sheet.getRange(i+1,7)
var fullMonths = Math.floor(amount/monthlyRepayment)
var remainderMonth = (amount/monthlyRepayment)-fullMonths
var remainderAmount = Math.round(remainderMonth*monthlyRepayment)
for (let j=1;j<=fullMonths+1;j++){
var incrementalMonths = new Date(startDate.setMonth(startDate.getMonth()+1)) ;
}
var newArray = [serial,id,monthlyRepayment];
var remainderArray = [serial,id,remainderAmount];
var reptArray = Array(fullMonths).fill(newArray);
var finalArray = [...reptArray,remainderArray]
Logger.log(finalArray)
var toPasteto = scheduleSheet.getRange(scheuduleLastRow+1,1,finalArray.length,3)
toPasteto.setValues(finalArray)
markScheduleDone.setValue ("Done")
}
}
I am close but I cant figure out how to join the incrementalMonths to the finalarray.
This is the first time im using a loop within a loop
Also any guidance if I could have done this better?
Kinldy requesting some guidance
I'm not sure if this is exactly what you are looking for but try this.
Notice I fill the array finalArray with all the newArrays so I only have to setValues() once. Same with markDone.
I increment the month but if the day happens to fall outside the number of days in a month it will increment to another day. So for any 28 or 30 day months there should be another check but I didn't do that.
My particular style of coding is to always use a try {} catch() {} block, always terminate a line with semicolon ;, and to use let instead of var whenever possible.
function myFunction() {
try {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("Loans");
var range = sheet.getDataRange();
var data = range.getValues()
var lastRow = range.getLastRow()
var scheduleSheet = ss.getSheetByName("Schedule")
var scheuduleLastRow = scheduleSheet.getDataRange().getLastRow();
let finalArray = [];
let markDone = [];
for(let i=1;i<lastRow;i++){
var serial = data [i][0];
var id = data [i][1];
var amount = data[i][2];
var monthlyRepayment = data [i][3];
var startDate = new Date (data [i][5]);
var fullMonths = Math.floor(amount/monthlyRepayment);
var remainderMonth = (amount/monthlyRepayment)-fullMonths;
var remainderAmount = Math.round(remainderMonth*monthlyRepayment);
let day = startDate.getDate();
if( day > 28 ) throw "This function has not adjusted for short months"
let month = startDate.getMonth();
let year = startDate.getFullYear();
let newArray = [];
for (let j=1;j<=fullMonths+1;j++){
month++;
if( month > 11 ) {
month = 0;
year++;
}
var date = new Date(year,month,day);
newArray.push([serial,id,monthlyRepayment,date])
}
newArray.push([serial,id,remainderAmount,date]);
finalArray = finalArray.concat(newArray);
Logger.log(newArray);
markDone.push(["Done"]);
}
sheet.getRange(2,7,markDone.length,1).setValues(markDone);
scheduleSheet.getRange(scheuduleLastRow+1,1,finalArray.length,4).setValues(finalArray);
}
catch(err) {
Logger.log(err)
}
}

Google Script - Macro to get data from a TABLE A and paste required values to Table B in sequence using LOOP

I seek help in finalizing a MACRO script for following task.
Basic requirements is to get data from 'Ref' tab (around 200 symbols) in a sequence to 'Mcontrol'!E3 (this tab imports a table from the Website)
From this table, sorted highest 2 values of Symbol/s is extracted and exported to 'OI EOD' tab,
i.e. required value is shown in 'OI EOD'! G5:K5.
Then, copy paste range 'OI EOD'! G5:K5 , to the matched row (symbol match to 'Mcontrol'!E3) in the table below ('OI EOD'!C6:C210).
I seek help in putting forEach condition in the macro. SO that next cycle of copy paste function is completed, for each new value in Cell_1 reference.
Hope ppl take notice of the help request from a novice and give good solution and guidance.
Sheet link is Following
https://docs.google.com/spreadsheets/d/1az2kas91KFxHcWhtWDg-g20hNYR-_zEiWPvYs-x42YU/edit?usp=sharing
Macro -
var wb = SpreadsheetApp.getActive();
var sh1= wb.getSheetByName('Mcontrol');
var sh2= wb.getSheetByName('OI EOD');
var R1 = 3
var C1 = 3
var R2 = 3
var C2 = 2
var R3 = 3
var C3 = 5
var cell_1 = sh1.getRange(R1,C1).getValue();
var cell_2 = sh1.getRange(R2,C2).getValue();
var cell_3 = sh1.getRange(R3,C3).getValue();
for(i=1;i<cell_2;i++);
cell_1 = i + 1;
sh1.getRange(R1,C1).setValue(cell_1);{
var Range_1 = sh2.getRange(6, 3, 300);
var row_i = 5 ; // source row no. for data copy paste
const Row_1 = row_i;
const Col_2 = 7;
const Row_Offet1 = 1;
const Col_Offet1 = 5;
var data = Range_1.getValues();
let ABC = cell_3;
let row = 1 + data.findIndex(users => {return users[0] == ABC});
var row_target = row + row_i ;
const sourceRange = sh2.getRange(Row_1,Col_2,Row_Offet1,Col_Offet1);
var destRange = sh2.getRange(row_target,Col_2,Row_Offet1,Col_Offet1);
sourceRange.copyTo(destRange,SpreadsheetApp.CopyPasteType.PASTE_VALUES,false);
for(k=1;k<cell_1.i;k++);
Logger.log(row_target);
Logger.log(k) ;
}
//NEXT
// cell_1=sh1.getRange(R1, C1);
// sh1.getRange(R1,C1).setValue(i);
}
}```
Thanks
Robin
Not sure if understand the task as a whole, so here is a guess.
This way you can get values from some start to some end 'symbols' (or numbers) and put these values in correct rows on the 'OI EOD' sheet:
function main() {
var start = 1;
var end = 5;
var ss = SpreadsheetApp.getActiveSpreadsheet();
var mcontrol_sheet = ss.getSheetByName('Mcontrol');
var oi_eod_sheet = ss.getSheetByName('OI EOD');
// get a list of all Symbols from column 'C' of the sheet 'OI EOD'
var symbols = oi_eod_sheet.getRange('c6:c').getValues().flat();
for (let i = start; i <= end; i++) {
// set the number i on the sheet 'Mcontrol' into the cell 'C3'
mcontrol_sheet.getRange('c3').setValue(i);
// wait to complete all the changes on the spreadsheet
SpreadsheetApp.flush();
// get the Symbol and Values from the range 'C5:K5' of the sheet 'OI EOD'
var [symbl, _, _, _, ...values] = oi_eod_sheet.getRange('c5:k5').getValues()[0];
// get the row index for this Symbol on the sheet 'Mcontrol'
var row = symbols.indexOf(symbl) + 6;
console.log({row}, {symbl}, {values});
// set the values on the sheet 'OI EOD' on the row with given index
oi_eod_sheet.getRange('g' + row + ':k' + row).setValues([values]);
}
}
It's up to you to decide how the start and end values could be defined. It can be values from two cells. Or it can be selected range. Or something else.

Add a status to each proccesed row in for loop that has an if statement with Google App Script

I've got a for loop in App script that is looking only at rows that have data in two columns. I'd like to set a status on each row that is actually processed, but the statuses get added to the wrong rows. When I add to i it adds to the whole length of the array, so I guess I shouldn't be trying to process each row, what am I doing wrong?
function auditReport() {
var sheetname = "Sheet1"; // name of data sheet ex. Form Responses 1
var colstoworkon = 10; // how many cols are filled with data f.e. by a form
var ss = SpreadsheetApp.getActiveSpreadsheet();
ss.setActiveSheet(ss.getSheetByName(sheetname));
var sheet = ss.getSheetByName(sheetname);
var data = sheet.getRange(3,1,sheet.getLastRow()-1,colstoworkon).getValues(); // starting with row 2 and column 1 as our upper-left most column,
//This makes it loops continuously and checks all not done rows
for (var i in data) {
if(data[i][1] && data[i][2]){//if email or copy are undefined just skip
var setStatus = sheet.getRange(i,4).setValue("done")
} // end of if
} // End of Loop
} //End of email function
Modification points:
In your script, from getRange(3,1,sheet.getLastRow()-1,colstoworkon), in this case, it is required to be getRange(3,1,sheet.getLastRow()-2,colstoworkon).
In the case of for (var i in data) {, i is the string type.
When you want to use sheet.getRange(i,4).setValue("done"), it is required to be sheet.getRange(Number(i) + 3, 4).setValue("done").
I thought that this might be the reason of your issue of but the statuses get added to the wrong rows..
In the case of if (data[i][1] && data[i][2]) {, if the value is 0, data[i][1] && data[i][2] is false.
When these points are reflected to your script, it becomes as follows.
Modified script:
function auditReport() {
var sheetname = "Sheet1";
var colstoworkon = 10;
var ss = SpreadsheetApp.getActiveSpreadsheet();
ss.setActiveSheet(ss.getSheetByName(sheetname));
var sheet = ss.getSheetByName(sheetname);
var data = sheet.getRange(3, 1, sheet.getLastRow() - 2, colstoworkon).getDisplayValues();
for (var i in data) {
if (data[i][1] && data[i][2]) {
var setStatus = sheet.getRange(Number(i) + 3, 4).setValue("done");
}
}
}
Or, your script can be also modified as follows. In this modification, done is put using the range list. By this, the process cost can be reduced a little.
function auditReport() {
var sheetname = "Sheet1";
var colstoworkon = 10;
var ss = SpreadsheetApp.getActiveSpreadsheet();
ss.setActiveSheet(ss.getSheetByName(sheetname));
var sheet = ss.getSheetByName(sheetname);
var data = sheet.getRange(3, 1, sheet.getLastRow() - 2, colstoworkon).getDisplayValues();
var ranges = data.map(([,b,c], i) => b && c ? `D${i + 3}` : "").filter(String);
if (ranges.length == 0) return;
sheet.getRangeList(ranges).setValue("done");
}
References:
for...in
getRangeList(a1Notations)

GMS2 Argument always returns undefined

I'm new to Game Maker Studio 2, whenever I try to call my script with scr_tile_collision(collision_tile_map_id, 16, velocity_[vector2_x]);, it states that the arguments are undefined. In my script I have the following, no matter whether I make the variables local or not, the script cannot seem to detect the params.
/// #param tile_map_id
/// #param tile_size
/// #param velocity_array
var tile_map_id = argument0;
var tile_size = argument1;
var velocity = argument2;
// For the velocity array
var vector2_x = 0;
var vector2_y = 1;
show_debug_message(tile_map_id); // no matter which variable is placed here, it is undefined.
// Move horizontally
x = x + velocity[vector2_x];
// Right collisions
if velocity[vector2_x] > 0 {
var tile_right = scr_collision(tile_map_id, [bbox_right-1, bbox_top], [bbox_right-1, bbox_bottom-1]);
if tile_right {
x = bbox_right & ~(tile_size-1);
x -= bbox_right-x;
velocity[# vector2_x] = 0;
}
} else {
var tile_left = scr_collision(tile_map_id, [bbox_left, bbox_top], [bbox_left, bbox_bottom-1]);
if tile_left {
x = bbox_left & ~(tile_size-1);
x += tile_size+x-bbox_left;
velocity[# vector2_x] = 0;
}
}
// Move vertically
y += velocity[vector2_y];
// Vertical collisions
if velocity[vector2_y] > 0 {
var tile_bottom = scr_collision(tile_map_id, [bbox_left, bbox_bottom-1], [bbox_right-1, bbox_bottom-1]);
if tile_bottom {
y = bbox_bottom & ~(tile_size-1);
y -= bbox_bottom-y;
velocity[# vector2_y] = 0;
}
} else {
var tile_top = scr_collision(tile_map_id, [bbox_left, bbox_top], [bbox_right-1, bbox_top]);
if tile_top {
y = bbox_top & ~(tile_size-1);
y += tile_size+y-bbox_top;
velocity[# vector2_y] = 0;
}
}
As of GMS2 2.3.0, the scripts in GMS2 needs to be within functions.
Normally these scripts should've been converted automatically, but perhaps that didn't happened for you. Try making a new script, and the function will appear there (along with a message in the comments about the new scripts), and you'll be able to assign parameters within that function.

create pause function for game using spritkit

i create a race game using spritkit
well i create button if the user click on it then it will pause the game , well my problem is that the Scene stop from moving but the car will stop slowly like the real car , i want to make stop without gravity
this is my code
physicsWorld.gravity = CGVectorMake(0.0,0.3);
physicsWorld.contactDelegate = self
this is player code
playerNode = SKSpriteNode(imageNamed: "car")
playerNode!.position = CGPoint(x: size.width / 2.0, y: 120.0)
playerNode!.physicsBody =
SKPhysicsBody(circleOfRadius: playerNode!.size.width / 2)
playerNode!.physicsBody!.dynamic = true
playerNode!.physicsBody!.linearDamping = 1.0
playerNode!.physicsBody!.allowsRotation = true
playerNode!.physicsBody!.categoryBitMask = CollisionCategoryPlayer
playerNode!.physicsBody!.contactTestBitMask =
CollisionCategoryPowerUpOrbs
playerNode!.physicsBody!.collisionBitMask = 0
foregroundNode!.addChild(playerNode!)
and finally this is the pause function
if (pasueornot){ // true or false
physicsWorld.gravity = CGVectorMake(0.0,gravitySpeed)
}
else{
physicsWorld.gravity = CGVectorMake(0.0,0.0) // the Scene stop from moving but the car will stop slowly like the real car pasueornot
}

Resources