A condition is omited - blender

I'm starting with blender and python, and in this activity we have to move in a certain way.
The movement is fine but for some reason in elif t <= 4.1 and t > 2.9: is omited so instead of having the object motionless in position 4.0 it goes executes posx = 0.0*t/5.6
import bpy
def custom_x_pos(frm):
""" Return object location for frame 'frm'
If time < 0, pos.x = 0
If time = 2.9, pos.x = 40
If time = 4.1, pos.x = 40
If time = 5.6, pos.x = 0
If time = 9.2, pos.x = 70
If time = 9.9, pos.x = 70
In between, linear interpolation
"""
# each frame is 1/24 secs. First, we compute time
t = frm/24.0
if t <=0 :
posx = 0.0
elif t <= 2.9:
posx = 4.0*t/2.9
elif t <= 4.1 and t > 2.9:
posx = 4.0
elif t <= 5.6 and t > 4.1:
posx = 0.0*t/5.6
elif t <= 9.2 and t > 5.6:
posx = 7.0*t/9.2
else: # if t > 9.2 secs
posx = 7.0
return posx
#
obj = bpy.context.active_object
# For frame 1, we set location and insert keyframe
frm = 1
obj.location[0] = custom_x_pos(frm)
obj.keyframe_insert(data_path='location',frame=frm)
# For frame 69.6, we set location and insert keyframe
frm = 69.6
obj.location[0] = custom_x_pos(frm)
obj.keyframe_insert(data_path='location',frame=frm)
# For frame 98.4, we set location and insert keyframe
frm = 98.4
obj.location[0] = custom_x_pos(frm)
obj.keyframe_insert(data_path='location',frame=frm)
# For frame 134.4, we set location and insert keyframe
frm = 134.4
obj.location[0] = custom_x_pos(frm)
obj.keyframe_insert(data_path='location',frame=frm)
# For frame 220.8, we set location and insert keyframe
frm = 220.8
obj.location[0] = custom_x_pos(frm)
obj.keyframe_insert(data_path='location',frame=frm)
# For frame 237.6, we set location and insert keyframe
frm = 237.6
obj.location[0] = custom_x_pos(frm)
obj.keyframe_insert(data_path='location',frame=frm)
I try the same code before with the sames conditions but i dont know why this in particular.

Related

How to color a plot lines based on amplitude

So I want to change the color of the blue vlines(matplotlib) in the above plot.
First I want to make the negative(< 0) values different color and take their absolute so that only amplitude is visible but they will be a different color than the negative ones. Positive values could remain unchanged.
minimum reproducible code as below:
import numpy as np
import random
import matplotlib.pyplot as plt
peakmzs = np.array([random.uniform(506, 2000) for i in range(2080)])
peakmzs = peakmzs[peakmzs.argsort()[::1]]
spec = np.zeros_like(peakmzs)
b = np.where((peakmzs > 1500) & (peakmzs < 1540))[0]
spec[b] = [random.uniform(0, 0.002) for i in range(len(b))]
b = np.where((peakmzs > 700) & (peakmzs < 820))[0]
spec[b] = [random.uniform(0, 0.05) for i in range(len(b))]
spec[300:302] = 0.07
b = np.where((peakmzs > 600) & (peakmzs < 650))[0]
spec[b] = [random.uniform(0, 0.03) for i in range(len(b))]
plt.vlines(peakmzs, spec, ymax=spec.max())
plt.show()
shp_values = np.zeros_like(peakmzs)
b = np.where((peakmzs > 1500) & (peakmzs < 1540))[0]
b_ = np.random.randint(1500, 1540, 10)
# print(b_)
shp_values[b] = [random.uniform(-0.003, 0.002) for i in range(len(b))]
shp_values[b_] = 0
b = np.where((peakmzs > 700) & (peakmzs < 820))[0]
shp_values[b] = [random.uniform(-0.004, 0.002) for i in range(len(b))]
b_ = np.random.randint(700, 820, 70)
shp_values[b_] = 0
# [random.uniform(-0.005, 0.003) for i in range(len(peakmzs))]
plt.plot(shp_values)
Based on the suggestion from #JohanC,
demo_shp = np.array(shapvalues[0][19])
colors = np.where(demo_shp < 0, 'cyan', 'pink')
plt.vlines(peakmzs, ymin=[0], ymax=demo_shp, colors=colors)
plt.show()

Need to plot multiple values over each number of iterations (python help)

I'm trying to plot the multiple values one gets for 'f_12' over a certain number of iterations. It should look something like points with high oscillations when there is low iterations 'N' and then it converges to a rough value of 0.204. I'm getting the correct outputs for 'f_12' but I'm having a really hard time doing the plots. New to python here.
start = time.time()
# looking for F_12 via monte carlo method
# Inputs
# N = number of rays to generate
N = 1000
# w = width of plates
w = 1
# h = vertical seperation of plates
# L = horizontal offset of plates (L=w=h)
L = 1
h = 1
p_points = 100
# counter for number of rays and number of hits
rays = 0
hits = 0
while rays < N:
rays = rays + 1
# random origin of rays along w on surface 1
Rx = random.uniform(0, 1)
Rt = random.uniform(0, 1)
Rph = random.uniform(0, 1)
x1 = Rx * w
# polar and azimuth angles - random ray directions
theta = np.arcsin(np.sqrt(Rt))
phi = 2*np.pi*Rph
# theta = np.arcsin(Rt)
xi = x1 + h*np.tan(theta)*np.cos(phi)
if xi >= L and xi <= (L+w):
hit = 1
else:
hit = 0
hits = hits + hit
gap = N/ p_points
r = rays%gap
if r == 0:
F = hits/ rays
plt.figure(figsize=(8, 4))
plt.plot(N, F, linewidth=2)
plt.xlabel("N - Rays")
plt.ylabel("F_12")
plt.show()
f_12 = hits/ N
print(f"F_12 = {f_12} at N = {N} iterations")
# Grab Currrent Time After Running the Code
end = time.time()
#Subtract Start Time from The End Time
total_time = end - start
f_time = round(total_time)
print(f"Running time = {f_time} seconds")

Offset rotation matrix

I'm working with 2 imu's. I need to offset all frames with the first frame from the sensor. I have created a fictive scenario, where I precisely know the rotation and the wanted result. I need the two sensors to show the same result when their initial (start) orientation is subtracted.
import numpy as np
# Sensor 0,1 and 2 start orientation in degrees
s0_x = 30
s0_y = 0
s0_z = 0
s1_x = 0
s1_y = 40
s1_z = 0
s2_x = 10
s2_y = 40
s2_z= -10
# Change from start frame 1
x1 = 20
y1 = 10
z1 = 0
# Change from start frame 2
x2 = 60
y2 = 30
z2 = 30
GCS= [[1,0,0],[0,1,0],[0,0,1]]
sensor0 = [[s0_x, s0_y, s0_z], [s0_x, s0_y, s0_z], [s0_x, s0_y, s0_z]]
sensor1 = [[s1_x, s1_y, s1_z], [s1_x + x1, s1_y + y1, s1_z + z1],[s1_x + x1 + x2, s1_y + y1+ y2, s1_z + z1+ z2]]
sensor2 = [[s2_x, s2_y, s2_z], [s2_x + x1, s2_y + y1, s2_z + z1], [s2_x + x1+ x2, s2_y + y1+ y2, s2_z + z1+ z2]]
def Rot_Mat_X(theta):
r = np.array([[1,0,0],[0,np.cos(np.deg2rad(theta)),-np.sin(np.deg2rad(theta))],[0,np.sin(np.deg2rad(theta)),np.cos(np.deg2rad(theta))]])
return r
# rotation the rotation matrix around the Y axis (input in deg)
def Rot_Mat_Y(theta):
r = np.array([[np.cos(np.deg2rad(theta)),0,np.sin(np.deg2rad(theta))],
[0,1,0],
[-np.sin(np.deg2rad(theta)),0,np.cos(np.deg2rad(theta))]])
return r
# rotation the rotation matrix around the Z axis (input in deg)
def Rot_Mat_Z(theta):
r = np.array([[np.cos(np.deg2rad(theta)),-np.sin(np.deg2rad(theta)),0],
[np.sin(np.deg2rad(theta)),np.cos(np.deg2rad(theta)),0],
[0,0,1]])
return r
# Creating the rotation matrices
r_sensor0 = []
r_sensor1= []
r_sensor2= []
for i in range(len(sensor1)):
r_sensor1_z = np.matmul(Rot_Mat_X(sensor1[i][0]),GCS)
r_sensor1_zy = np.matmul(Rot_Mat_Y(sensor1[i][1]),r_sensor1_z)
r_R_Upperarm_medial_zyx = np.matmul(Rot_Mat_Z(sensor1[i][2]),r_sensor1_zy )
r_sensor1.append(r_R_Upperarm_medial_zyx )
r_sensor2_z = np.matmul(Rot_Mat_X(sensor2[i][0]),GCS)
r_sensor2_zy = np.matmul(Rot_Mat_Y(sensor2[i][1]),r_sensor2_z )
r_sensor2_zyx = np.matmul(Rot_Mat_Z(sensor2[i][2]),r_sensor2_zy )
r_sensor2.append(r_sensor2_zyx )
r_start_sensor1 = r_sensor1[0]
r_start_sensor2 = r_sensor2[0]
r_offset_sensor1 = []
r_offset_sensor2 = []
for i in range(len(sensor0)):
r_offset_sensor1.append(np.matmul(np.transpose(r_start_sensor1),r_sensor1[i]))
r_offset_sensor2.append(np.matmul(np.transpose(r_start_sensor2),r_sensor2[i]))
# result:
r_offset_sensor1[0] = [[1,0,0],[0,1,0],[0,0,1]]
r_offset_sensor1[1] = [[0.984,0.059,0.163],[0,0.939,-0.342],[-0.173,0.336,0.925]]
r_offset_sensor1[2] = [[0.748,0.466,0.471],[0.086,0.635,-0.767],[-0.657,0.615,0.434]]
r_offset_sensor2[0] = [[1,0,0],[0,1,0],[0,0,1]]
r_offset_sensor2[1] = [[0.984,0.086,0.150],[-0.03,0.938,-0.344],[-0.171,0.334,0.926]]
r_offset_sensor2[2] = [[0.748,0.541,0.383],[-0.028,0.603,-0.797],[-0.662,0.585,0.466]]
I expect the result of sensors 1 and 2 to be equal for all frames but it doesn't? And they should be:
frame[0] = [1,0,0],[0,1,0],[0,0,1]
frame[1] = [0.984,0,0.173],[0.059,0.939,-0.336],[-0.163,0.342,0.9254]
frame[2] = [0.750,-0.433,0.50],[0.625,0.216,-0.750],[0.216,0.875,0.433]

Deleting new lines once the price crosses it after the line was created

I have been creating new lines in pinescript that extend and want to delete them when the future price hits or crosses the line price. Any help will be appreciated.
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
//#version=4
study("My RS", overlay=true)
float d = 1.0
t = time("60")
start = na(t[1]) or t > t[1]
ticker = syminfo.ticker
src=input(title="Source", type=input.source, defval=open)
float d_r = na
float d_s = na
if (start)
d_r := src + d
d_s := src - d
line lr = na
line ls = na
// drawing r/s lines every hour
if (start)
lr := line.new(x1 = bar_index, y1 = d_r, x2 = bar_index - 1, y2 = d_r, extend = extend.left, color = color.red, width = 2, style = line.style_dashed)
ls := line.new(x1 = bar_index, y1 = d_s, x2 = bar_index - 1, y2 = d_s, extend = extend.left, color = color.lime, width = 2, style = line.style_dashed)
// want to delete lines when the future price crosses the line, which is not working for me
for i = 0 to 100
if not na(lr[i]) and close < high[i]
line.delete(lr[i])
if not na(ls[i]) and close < low[i]
line.delete(ls[i])
you need to get the coordinate of the lines, so use inside a loop if line.get_y1(id[i]) < close if it true, line.delete(id[i]).
Is this what're you looking for?

How to make a death animation in LOVE2D?

I have created collision for the player and enemies (the collision isn't perfect but works for the most part) in my game but am having a hard time figuring out how to create a death animation for the player.
I want the player's ship to explode when the enemies hit you, how would I go about this?
Here is my player file:
Player = Class{}
function Player:init(x, y, width, height)
self.player = {}
self.x = x
self.y = y
self.height = height
self.dx = 0
self.image = love.graphics.newImage('images/player.png')
self.width = self.image:getWidth()
self.fire_sound = love.audio.newSource('sounds/laser.wav', 'static')
self.fire_sound:setVolume(.25)
self.player_explosion = love.audio.newSource('sounds/player_explosion.wav', 'static')
self.player_explosion:setVolume(25)
self.cooldown = 10
self.bullets = {}
end
function Player:update(dt)
self.x = self.x + self.dx * dt
if self.x <= 0 then
self.dx = 0
self.x = 0
end
if self.x >= WINDOW_WIDTH - self.width * 4 then
self.dx = 0
self.x = WINDOW_WIDTH - self.width * 4
end
end
function Player:fire()
if self.cooldown <= 0 then
love.audio.play(player.fire_sound)
if BULLET_COUNTER >= 1 then
love.audio.stop(player.fire_sound)
love.audio.play(player.fire_sound)
self.cooldown = 30
bullet = {}
bullet.x = player.x + 25
bullet.y = player.y + 5
table.insert(self.bullets, bullet)
BULLET_COUNTER = 0
return
end
self.cooldown = 10
bullet = {}
bullet.x = self.x + 25
bullet.y = self.y + 5
table.insert(self.bullets, bullet)
BULLET_COUNTER = BULLET_COUNTER + 1
end
end
function Player:render()
love.graphics.setColor(255, 255, 255)
love.graphics.draw(self.image, self.x, self.y, 0, 4)
end
function Player:checkCollision(enemies)
for i,e in ipairs(enemies) do
if e.y + e.height >= self.y and e.y <= self.y + self.height and e.x <= self.x + self.width and e.x + e.width >= self.x + self.width then
love.audio.stop(self.player_explosion)
love.audio.play(self.player_explosion)
table.remove(enemies, i)
LIVES = LIVES - 1
end
end
end
Here is my main file if you need it:
Class = require 'class'
require 'Player'
GAME_STATE = 'start'
WINDOW_WIDTH = 720
WINDOW_HEIGHT = 900
love.window.setMode(WINDOW_WIDTH, WINDOW_HEIGHT)
SCORE = 0
LIVES = 3
PLAYER_SPEED = 300
-- map variables
map = {}
map.image = love.graphics.newImage('images/background_final.png')
map.width = 720
map.height = 900
map.music = love.audio.newSource('sounds/Battle-in-the-Stars.wav', 'static')
-- enemy variables
enemy = {}
enemies_controller = {}
enemies_controller.enemies = {}
alienImage = love.graphics.newImage('images/alien2.png')
alienship1_Image = love.graphics.newImage('images/enemyship1.png')
alienship2_Image = love.graphics.newImage('images/enemyship4.png')
enemies_controller.explosion = love.audio.newSource('sounds/explosion.wav', 'static')
enemies_controller.explosion:setVolume(.25)
spawnTimer = 0
spawnTimer_Max = 0.75
SMALL_WIDTH = 70
SMALL_HEIGHT = 70
-- star variables for warp effect
star = {}
stars_controller = {}
stars_controller.stars = {}
starSpawnTimer = 0
starSpawnTimer_Max = 0.25
STAR_WIDTH = 100
STAR_HEIGHT = 100
BULLET_COUNTER = 0
-- this function allows us to scale an image we created to a desired height and width
function getImageScaleForNewDimensions(image, newWidth, newHeight)
local currentWidth, currentHeight = image:getDimensions()
return ( newWidth / currentWidth ), ( newHeight / currentHeight )
end
-- check collisions for enemies and bullets
function checkCollisions(enemies, bullets)
for i,e in ipairs(enemies) do
for j,b in ipairs(bullets) do
-- checks if the hitboxes for the bullet and the enemy collide
-- if they do remove the enemy and the bullet that collided
if b.y <= e.y + e.height and b.x > e.x and b.x < e.x + e.width then
love.audio.stop(enemies_controller.explosion)
table.remove(enemies, i)
table.remove(bullets, j)
love.audio.play(enemies_controller.explosion)
SCORE = SCORE + 10
end
end
end
end
function love.load()
love.graphics.setDefaultFilter('nearest', 'nearest')
love.window.setTitle('Space Attack')
title_largeFont = love.graphics.newFont('fonts/Mario-Kart-DS.ttf', 40)
title_smallFont = love.graphics.newFont('fonts/Mario-Kart-DS.ttf', 20)
largeFont = love.graphics.newFont('fonts/04B_30__.TTF', 32)
smallFont = love.graphics.newFont('fonts/04B_30__.TTF', 20)
love.graphics.setFont(largeFont)
player = Player(WINDOW_WIDTH / 2 - 40, WINDOW_HEIGHT - 100, 10, 10)
map.music:setLooping(true)
map.music:setVolume(.25)
map.music:play()
end
function enemies_controller:spawnEnemy(x, y, n)
enemy = {}
enemy.x = x
enemy.y = y
enemy.width = SMALL_WIDTH
enemy.height = SMALL_HEIGHT
enemy.bullets = {}
enemy.cooldown = 10
-- n is a random variable that determines what type of enemy spawns
if n == 0 then
enemy.image = alienImage
enemy.speed = 5
elseif n == 1 then
enemy.image = alienship1_Image
enemy.speed = 6
else
enemy.image = alienship2_Image
enemy.speed = 7
end
table.insert(self.enemies, enemy)
end
function stars_controller:spawnStars(x, y)
star = {}
star.x = x
star.y = y
star.speed = 10
star.image = love.graphics.newImage('images/star.png')
star.width = SMALL_WIDTH
star.height = SMALL_HEIGHT
table.insert(self.stars, star)
end
function love.update(dt)
player.cooldown = player.cooldown - 1
checkCollisions(enemies_controller.enemies, player.bullets)
player:checkCollision(enemies_controller.enemies)
-- checks spawn timer, if > 0 don't spawn an enemy but if it is spawn an enemy
if spawnTimer > 0 then
spawnTimer = spawnTimer - dt
else
if GAME_STATE == 'play' then
enemies_controller:spawnEnemy(love.math.random(0, WINDOW_WIDTH - SMALL_WIDTH), 0, love.math.random(0,2))
spawnTimer = spawnTimer_Max
end
end
-- same situation as spawn timer for enemies, but this is for the warp effect
if starSpawnTimer > 0 then
starSpawnTimer = starSpawnTimer - dt
else
stars_controller:spawnStars(love.math.random(0, WINDOW_WIDTH - SMALL_WIDTH), 0)
starSpawnTimer = starSpawnTimer_Max
end
-- checking user input to move left and right
if love.keyboard.isDown('right') then
if GAME_STATE == 'play' then
player.dx = PLAYER_SPEED
end
elseif love.keyboard.isDown('left') then
if GAME_STATE == 'play' then
player.dx = -PLAYER_SPEED
end
else
player.dx = 0
end
-- checking user input for firing function
if love.keyboard.isDown('space') then
if GAME_STATE == 'play' then
player:fire()
end
end
-- this removes enemies if they are too far off the scree
-- also how the enemies move downards
-- NEED TO ADD MOVEMENT FUNCTIONS HERE FOR DIFFERENT ENEMIES
for i,e in ipairs(enemies_controller.enemies) do
e.y = e.y + e.speed
if e.y > WINDOW_HEIGHT then
table.remove(enemies_controller.enemies, i)
end
end
-- removes bullets if they travel too far off the screen
-- this also moves the bullets upwards
for i,v in ipairs(player.bullets) do
if v.y < 0 then
table.remove(player.bullets, i)
end
v.y = v.y - 8
end
-- removes stars if they travel too far off screen
-- moves the stars to create warp effect
for i,s in ipairs(stars_controller.stars) do
s.y = s.y + s.speed
if s.y > WINDOW_HEIGHT then
table.remove(stars_controller.stars, i)
end
end
-- checks lives to determine game state
if LIVES == 0 then
GAME_STATE = 'end'
end
player:update(dt)
end
-- key pressed function so we can exit the game and start the game
function love.keypressed(key)
if key == 'escape' then
love.event.quit()
elseif key == 'enter' or key == 'return' then
if GAME_STATE == 'start' then
GAME_STATE = 'play'
end
end
end
function love.draw()
-- checks gamestate and if it is
if GAME_STATE == 'start' then
-- draw the warp effect
for _,s in pairs(stars_controller.stars) do
local scaleX, scaleY = getImageScaleForNewDimensions(s.image, STAR_WIDTH, STAR_HEIGHT)
love.graphics.draw(s.image, s.x, s.y, 0, 2, 4)
end
-- draw the player
player:render()
love.graphics.setColor(200, 0, 200, 255)
love.graphics.setFont(title_largeFont)
love.graphics.print('WELCOME TO SPACE ATTACK!', WINDOW_WIDTH / 2 - 290, WINDOW_HEIGHT / 2)
love.graphics.setFont(title_smallFont)
love.graphics.print('press ENTER to begin!', WINDOW_WIDTH / 2 - 110, WINDOW_HEIGHT / 2 + 100)
end
if GAME_STATE == 'play' then
-- draw the map
love.graphics.setColor(255, 255, 255)
local map_width, map_height = getImageScaleForNewDimensions(map.image, map.width, map.height)
love.graphics.draw(map.image, 0, 0, 0, map_width, map_height)
-- draw the enemies
for _,e in pairs(enemies_controller.enemies) do
local scaleX, scaleY = getImageScaleForNewDimensions(e.image, SMALL_WIDTH, SMALL_HEIGHT)
love.graphics.draw(e.image, e.x, e.y, 0, scaleX, scaleY)
end
-- draw the warp effect
for _,s in pairs(stars_controller.stars) do
love.graphics.draw(s.image, s.x, s.y, 0, 1, 4)
end
-- draw the player
player:render()
-- draw the bullets
love.graphics.setColor(255, 255, 255)
for _,v in pairs(player.bullets) do
love.graphics.rectangle('fill', v.x, v.y, 10, 10)
end
displayScore()
displayLives()
end
if GAME_STATE == 'end' then
love.audio.stop()
love.graphics.setColor(200, 0, 200, 255)
love.graphics.setFont(title_largeFont)
love.graphics.print('GAME OVER!', WINDOW_WIDTH / 2 - 120, WINDOW_HEIGHT / 2)
love.graphics.setFont(title_smallFont)
love.graphics.print('score ' .. tostring(SCORE), WINDOW_WIDTH / 2 - 60, WINDOW_HEIGHT / 2 + 50)
end
end
function displayScore()
if GAME_STATE == 'play' then
love.graphics.setColor(0, 255, 0, 255)
love.graphics.setFont(largeFont)
love.graphics.print('Score: ' .. tostring(SCORE), WINDOW_WIDTH / 2 - 130, 10)
end
end
function displayLives()
if GAME_STATE == 'play' then
love.graphics.setColor(255, 0, 0, 255)
love.graphics.setFont(smallFont)
love.graphics.print('Lives: ' .. tostring(LIVES), WINDOW_WIDTH - 150, 10)
end
end
I want the player's ship to explode when the enemies hit you, how would I go about this?
I assume you are asking about creating the actual visual effect of an explosion. LÖVE's particle system has all the functionality to create that sort of animation / effect, but can be a bit overkill if you are just starting out.
A simple alternative would be to remove the player's ship and replace it with an animated sprite of an explosion. You could use a library to handle the animation code for you, or just use it as a reference point for your own animation code.
An animation usually consists of multiple frames or images which are displayed in a sequence. E.g. a very simple animation could look like this:
Frame: Small Explosion
Frame: Explosion gets bigger
Frame: Explosion gets smaller again
Frame: Smoke appears
Frame: Smoke vanishes and animation is finished
Each of these frames would be contained in one big image or spritesheet.
In LÖVE you will have to load the spritesheet and divide it into its frames by using quads:
local spritesheet = love.graphics.newImage("animation.png")
-- Create a quad for each frame in the spritesheet.
-- Here we assume that each frame is a 16x16 square inside of the spritesheet.
local animation = {
love.graphics.newQuad(0, 0, 16, 16, spritesheet:getDimensions()),
love.graphics.newQuad(16, 0, 16, 16, spritesheet:getDimensions()),
-- more frames
}
-- To display the animation we draw one quad each frame and then update the index variable.
-- Of course in a real game you'd add a delay between each frame and check for the boundaries
-- of the array and so on.
local i = 1
function love.draw()
love.graphics.draw(spritesheet, animation[i], 50, 50)
i = i + 1
end
This is not a perfect example, but I hope it shows the general idea of how animations can work.